{"record":{"id":"da32297290d9b9ad","repo":"hibernate/hibernate-orm","slug":"entity-may-not-override-the-inheritance-mappi","errorCode":null,"errorMessage":"Entity '{}' may not override the inheritance mapping strategy '{}' of its hierarchy' (each entity hierarchy has a single inheritance mapping strategy)","messagePattern":"Entity '(.+?)' may not override the inheritance mapping strategy '(.+?)' of its hierarchy' \\(each entity hierarchy has a single inheritance mapping strategy\\)","errorType":"exception","errorClass":"AnnotationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotationBinder.java","lineNumber":565,"sourceCode":"\t\t\t\t\tstate.setType( inheritanceType );\n\t\t\t\t}\n\t\t\t}\n\t\t\tswitch ( classType ) {\n\t\t\t\tcase ENTITY, MAPPED_SUPERCLASS, EMBEDDABLE:\n\t\t\t\t\tinheritanceStatePerClass.put( classDetails, state );\n\t\t\t}\n\t\t}\n\t\treturn inheritanceStatePerClass;\n\t}\n\n\tprivate static void checkMixedInheritance(ClassDetails classDetails, InheritanceState superclassState, InheritanceState state) {\n\t\tfinal var inheritanceType = state.getType();\n\t\tfinal var superclassInheritanceType = superclassState.getType();\n\t\tif ( inheritanceType != null && superclassInheritanceType != null ) {\n\t\t\tfinal boolean nonDefault = SINGLE_TABLE != inheritanceType;\n\t\t\tfinal boolean mixingStrategy = inheritanceType != superclassInheritanceType;\n\t\t\tif ( nonDefault && mixingStrategy ) {\n\t\t\t\tthrow new AnnotationException( \"Entity '\" + classDetails.getName()\n\t\t\t\t\t\t+ \"' may not override the inheritance mapping strategy '\" + superclassInheritanceType\n\t\t\t\t\t\t+ \"' of its hierarchy\"\n\t\t\t\t\t\t+ \"' (each entity hierarchy has a single inheritance mapping strategy)\" );\n\t\t\t}\n\t\t}\n\t}\n}\n","sourceCodeStart":547,"sourceCodeEnd":573,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotationBinder.java#L547-L573","documentation":"An entity declares an '@Inheritance' strategy that differs from the strategy already established by its mapped superclass/ancestor in the same hierarchy. JPA allows exactly ONE inheritance strategy per entity hierarchy, declared on the root; Hibernate enforces this whenever the subclass picks a non-default strategy that conflicts with the hierarchy's (non-default = anything other than the SINGLE_TABLE default).","triggerScenarios":"Root entity '@Inheritance(JOINED)' and a subclass declaring '@Inheritance(SINGLE_TABLE)' (or TABLE_PER_CLASS); ancestors chain where an intermediate class redeclares @Inheritance with a different type; checkMixedInheritance fires when both this state's type and the superclass state's type are non-null, differ, and the subclass type is not the SINGLE_TABLE default.","commonSituations":"Copy-pasting the root's @Inheritance line onto subclasses and editing the strategy per class; merging two hierarchies that used different strategies; believing each level can pick its own mapping strategy.","solutions":["Remove '@Inheritance' from the subclass named in the message — only the hierarchy root defines the strategy.","Choose ONE strategy for the whole hierarchy and declare it once on the root @Entity.","If different branches truly need different strategies, split them into separate, independent hierarchies (separate roots)."],"exampleFix":"// before\n@Entity\n@Inheritance(strategy = InheritanceType.JOINED)\nabstract class BillingDocument { @Id Long id; }\n\n@Entity\n@Inheritance(strategy = InheritanceType.SINGLE_TABLE) // -> error: override\nclass Invoice extends BillingDocument { ... }\n\n// after\n@Entity\nclass Invoice extends BillingDocument { ... } // strategy only on the root","handlingStrategy":"validation","validationCode":"// Guard: @Inheritance only on hierarchy roots, one strategy per hierarchy\nClass<?> c = cls;\nwhile (c.getSuperclass() != null) {\n    c = c.getSuperclass();\n    Inheritance parent = c.getAnnotation(Inheritance.class);\n    Inheritance mine = cls.getAnnotation(Inheritance.class);\n    if (parent != null && mine != null\n            && mine.strategy() != parent.strategy()) {\n        throw new IllegalStateException(cls.getName()\n            + \" overrides hierarchy inheritance strategy\");\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    Metadata md = sources.buildMetadata();\n} catch (AnnotationException e) {\n    // 'may not override the inheritance mapping strategy' -> delete @Inheritance\n    // from the subclass; keep one strategy on the root\n    throw newConfigurationException(\"Inheritance strategy conflict\", e);\n}","preventionTips":["Declare @Inheritance once, on the root entity; subclasses inherit the strategy implicitly.","If branches need different strategies, split into independent hierarchies with separate roots."],"tags":["hibernate","jpa","inheritance","orm-mapping","entity-hierarchy"],"backgroundTag":"inheritance-strategy-conflict","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}