{"record":{"id":"01a5758ae30a0989","repo":"hibernate/hibernate-orm","slug":"cannot-use-identity-column-key-generation-with-un","errorCode":null,"errorMessage":"Cannot use identity column key generation with <union-subclass> mapping for: %s","messagePattern":"Cannot use identity column key generation with <union-subclass> mapping for: (.+?)","errorType":"exception","errorClass":"MappingException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java","lineNumber":219,"sourceCode":"\t\t\t\t\t\tgetIdentifierMapping(),\n\t\t\t\t\t\ttableName,\n\t\t\t\t\t\tgetIdentifierColumnNames()\n\t\t\t\t)\n\t\t);\n\n\t\tvisitAttributeMappings( (attribute) -> {\n\t\t\tbuilder.addAttribute( attribute );\n\t\t\tattribute.forEachSelectable( (selectableIndex, selectable)\n\t\t\t\t\t-> builder.addColumn( attribute, ColumnDescriptor.from( selectable ) ) );\n\t\t} );\n\n\t\t// Union subclass has only one table, so entity-wide flag equals table flag\n\t\treturn new EntityTableDescriptor[] { builder.build( builder.isSelfReferential ) };\n\t}\n\n\tprotected void validateGenerator() {\n\t\tif ( getGenerator() instanceof IdentityGenerator ) {\n\t\t\tthrow new MappingException( \"Cannot use identity column key generation with <union-subclass> mapping for: \" + getEntityName() );\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean containsTableReference(String tableExpression) {\n\t\tfor ( String subclassTableExpression : subclassTableExpressions ) {\n\t\t\tif ( subclassTableExpression.equals( tableExpression ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\n\t@Override\n\tpublic UnionTableReference createPrimaryTableReference(\n\t\t\tSqlAliasBase sqlAliasBase,\n\t\t\tSqlAstCreationState creationState) {","sourceCodeStart":201,"sourceCodeEnd":237,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java#L201-L237","documentation":"TABLE_PER_CLASS inheritance (union-subclass) answers polymorphic queries with UNION over the concrete class tables, which cannot produce meaningful results if each table independently assigns primary keys via the database IDENTITY mechanism. UnionSubclassEntityPersister.validateGenerator() therefore rejects IdentityGenerator at SessionFactory boot with a MappingException naming the entity.","triggerScenarios":"@Inheritance(strategy = TABLE_PER_CLASS) with @GeneratedValue(strategy = GenerationType.IDENTITY) on the root identifier; hbm.xml <union-subclass> with <generator class=\"native\"/> on a dialect where native resolves to identity (MySQL, SQL Server); dialect-native generation picking identity implicitly.","commonSituations":"Porting an app from SINGLE_TABLE to TABLE_PER_CLASS on MySQL where auto-increment was used; generated mappings defaulting to IDENTITY; using database auto-increment columns out of habit on union hierarchies.","solutions":["Switch to a shared generator: @GeneratedValue(strategy = SEQUENCE) with @SequenceGenerator on the root","Use a TABLE generator, UUID strategy, or assigned identifiers if the database has no sequences","If IDENTITY columns are mandatory, switch the hierarchy to JOINED inheritance instead","Avoid generator class \"native\" on identity-only dialects - pin the strategy explicitly"],"exampleFix":"// before\n@Entity\n@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)\npublic class Vehicle {\n    @Id @GeneratedValue(strategy = GenerationType.IDENTITY) // rejected\n    Long id;\n}\n\n// after\n@Entity\n@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)\npublic class Vehicle {\n    @Id\n    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = \"veh_seq\")\n    @SequenceGenerator(name = \"veh_seq\", sequenceName = \"vehicle_seq\", allocationSize = 50)\n    Long id;\n}","handlingStrategy":"validation","validationCode":"// fail fast in CI: TABLE_PER_CLASS + IDENTITY is rejected by Hibernate\nfor (Class<?> e : entityClasses) {\n    Inheritance inh = e.getAnnotation(Inheritance.class);\n    GeneratedValue gv = e.getAnnotation(GeneratedValue.class);\n    if (inh != null && inh.strategy() == InheritanceType.TABLE_PER_CLASS\n            && gv != null && gv.strategy() == GenerationType.IDENTITY) {\n        throw new IllegalStateException(\"TABLE_PER_CLASS + IDENTITY not supported: \" + e.getName());\n    }\n}","typeGuard":null,"tryCatchPattern":"try { sessionFactory = cfg.buildSessionFactory(); } catch (MappingException e) { if (e.getMessage().contains(\"identity column key generation\")) { /* switch the hierarchy to SEQUENCE/TABLE/UUID generation */ } throw e; }","preventionTips":["Default new hierarchies to SEQUENCE generation; reserve IDENTITY for non-inherited tables","Never rely on generator class 'native' for union-subclass mappings on identity-only databases","Add a config-scan test for the TABLE_PER_CLASS + IDENTITY combination"],"tags":["hibernate","orm","table-per-class","union-subclass","identity-generator","mapping"],"backgroundTag":"identity-generator-unsupported","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}