{"record":{"id":"add36224d10b02e5","repo":"hibernate/hibernate-orm","slug":"multiple-check-constraints-not-supported-for-aggre","errorCode":null,"errorMessage":"Multiple check constraints not supported for aggregate columns","messagePattern":"Multiple check constraints not supported for aggregate columns","errorType":"exception","errorClass":"MappingException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardTableExporter.java","lineNumber":399,"sourceCode":"\t\t\t\t\t\t);\n\t\t\t\t\t\tif ( subColumn.isNullable() ) {\n\t\t\t\t\t\t\tbuf.append( ')' );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tseparator = \" and \";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn separator;\n\t}\n\n\tprivate static String getCheckConstraint(Column subColumn) {\n\t\tfinal var checkConstraints = subColumn.getCheckConstraints();\n\t\tif ( checkConstraints.isEmpty() ) {\n\t\t\treturn null;\n\t\t}\n\t\telse if ( checkConstraints.size() > 1 ) {\n\t\t\tthrow new MappingException( \"Multiple check constraints not supported for aggregate columns\" );\n\t\t}\n\t\telse {\n\t\t\treturn checkConstraints.get(0).getConstraint();\n\t\t}\n\t}\n\n\tprivate String tableCreateString(Table table) {\n\t\tfinal String createTableString =\n\t\t\t\ttable.hasPrimaryKey()\n\t\t\t\t\t\t? dialect.getCreateTableString()\n\t\t\t\t\t\t: dialect.getCreateMultisetTableString();\n\t\tfinal String type = table.getType();\n\t\treturn isBlank( type )\n\t\t\t\t? createTableString\n\t\t\t\t: createTableString.replaceFirst( \" (?i:table)\",\n\t\t\t\t\t\t' ' + type + \" table\" );\n\t}\n","sourceCodeStart":381,"sourceCodeEnd":417,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardTableExporter.java#L381-L417","documentation":"When a table column is an aggregate (embeddable/component) rendered inline, Hibernate can attach at most one check constraint to the sub-column. If the mapped sub-column accumulates more than one check definition, this MappingException aborts CREATE TABLE string building. It flags an over-constrained embedded mapping, not a database runtime error.","triggerScenarios":"An @Embeddable (or hbm.xml component) used via @Embedded/@EmbeddedId where one of its columns ends up with multiple check constraints: checks declared at more than one mapping layer for the same sub-column, duplicated column definitions inside the component, or programmatic metadata adding several checks to one component column. Thrown from getCheckConstraint while StandardTableExporter renders the aggregate column.","commonSituations":"Embeddables shared across entities where both the embeddable and each owner add checks; XML mappings migrated to annotations leaving the old check attribute active; duplicated <column check=...> entries in component property mappings.","solutions":["Find the embeddable sub-column named by the failing mapping and keep a single check constraint on it, merging conditions with AND if both must hold.","Move additional constraints out of the aggregate: declare them as table-level @Check on the owning entity or handle them in migration scripts.","De-duplicate the mapping layers (remove the XML check or the annotation check) so only one definition reaches the sub-column."],"exampleFix":"<!-- before: same component column carries two checks -->\n<component name=\"address\" class=\"Address\">\n  <property name=\"zip\">\n    <column name=\"zip\" check=\"length(zip) > 0\"/>\n    <column name=\"zip\" check=\"zip ~ '^[0-9]+$'\"/>\n  </property>\n</component>\n\n<!-- after: one merged check -->\n<component name=\"address\" class=\"Address\">\n  <property name=\"zip\">\n    <column name=\"zip\" check=\"length(zip) > 0 AND zip ~ '^[0-9]+$'\"/>\n  </property>\n</component>","handlingStrategy":"validation","validationCode":"// after building Metadata, assert no aggregate sub-column carries more than one check\nmetadata.getDatabase().getNamespaces().stream()\n        .flatMap(ns -> ns.getTables().stream())\n        .flatMap(t -> Stream.concat(t.getColumns().stream(),\n                t.getColumnIterator /* embeddable sub-columns */))\n        .forEach(c -> { if (c.getCheckConstraints().size() > 1\n                && cisAggregateSubColumn(c)) { throw new IllegalStateException(\"Multiple checks on \" + c); } });","typeGuard":null,"tryCatchPattern":"try {\n    new SchemaExport(metadata).createOnly();\n} catch (MappingException e) {\n    if (e.getMessage() != null && e.getMessage().equals(\"Multiple check constraints not supported for aggregate columns\")) {\n        // reduce the embeddable sub-column to one merged check (AND) and retry\n    } else { throw e; }\n}","preventionTips":["Declare at most one check per embeddable sub-column; merge conditions with AND.","Prefer table-level @Check on the owning entity over per-subcolumn checks inside aggregates.","When migrating XML to annotations, remove the old check attributes instead of layering them."],"tags":["hibernate","embeddable","check-constraint","mapping","ddl"],"backgroundTag":"unsupported-mapping-constraint","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}