{"record":{"id":"454e61885d246435","repo":"hibernate/hibernate-orm","slug":"entities-s-and-s-are-mapped-with-the-same-di","errorCode":null,"errorMessage":"Entities [%s] and [%s] are mapped with the same discriminator value '%s'.","messagePattern":"Entities \\[(.+?)\\] and \\[(.+?)\\] are mapped with the same discriminator value '(.+?)'\\.","errorType":"exception","errorClass":"MappingException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java","lineNumber":309,"sourceCode":"\n\t\t// Don't hold a reference to an empty HashMap:\n\t\tsubclassesByDiscriminatorValue = toSmallMap( subclassesByDiscriminatorValueLocal );\n\t}\n\n\tprivate static boolean isDiscriminatorInsertable(PersistentClass persistentClass) {\n\t\treturn !persistentClass.isDiscriminatorValueNull()\n\t\t\t&& !persistentClass.isDiscriminatorValueNotNull()\n\t\t\t&& persistentClass.isDiscriminatorInsertable()\n\t\t\t&& !persistentClass.getDiscriminator().hasFormula();\n\t}\n\n\tprivate static void addSubclassByDiscriminatorValue(\n\t\t\tMap<DiscriminatorValue, String> subclassesByDiscriminatorValue,\n\t\t\tDiscriminatorValue discriminatorValue,\n\t\t\tString entityName) {\n\t\tfinal String mappedEntityName = subclassesByDiscriminatorValue.put( discriminatorValue, entityName );\n\t\tif ( mappedEntityName != null ) {\n\t\t\tthrow new MappingException(\n\t\t\t\t\t\"Entities [\" + entityName + \"] and [\" + mappedEntityName\n\t\t\t\t\t\t\t+ \"] are mapped with the same discriminator value '\" + discriminatorValue + \"'.\"\n\t\t\t);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean isInverseTable(int j) {\n\t\treturn isInverseTable[j];\n\t}\n\n\t@Override\n\tpublic String getDiscriminatorColumnName() {\n\t\treturn discriminatorColumnName;\n\t}\n\n\t@Override\n\tpublic String getDiscriminatorColumnReaders() {","sourceCodeStart":291,"sourceCodeEnd":327,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java#L291-L327","documentation":"In SINGLE_TABLE inheritance, Hibernate registers each entity of a hierarchy under its discriminator value in one map (subclassesByDiscriminatorValue). addSubclassByDiscriminatorValue detects that the same value was already registered and throws a MappingException naming both entities and the duplicated value. Boot fails because two rows with the same discriminator value could not be resolved to distinct classes.","triggerScenarios":"Two @DiscriminatorValue(\"X\") annotations on sibling subclasses (or one equal to the root's); values that collide after the discriminator type normalizes them (\"A\" vs \"a\" with a case-insensitive string type, 1 vs \"1\" with a custom DiscriminatorType); both subclasses (or the root and a subclass) leaving the value null.","commonSituations":"Copy-pasted subclasses that kept the same discriminator value; short codes like \"S\"/\"s\" meaning different things; refactors that merged or renamed branches of a hierarchy; custom discriminator types that map multiple inputs to the same key.","solutions":["Assign a unique @DiscriminatorValue to every class in the hierarchy (including the root)","Check for values that are equal after case-folding or trimming and make them strictly distinct","Review custom DiscriminatorType implementations for normalization that collapses distinct values","Add a bootstrap test that asserts discriminator-value uniqueness per hierarchy (see validation)"],"exampleFix":"// before: two subclasses share the same value\n@Entity @DiscriminatorValue(\"A\") public class TypeA extends Base { }\n@Entity @DiscriminatorValue(\"A\") public class TypeB extends Base { }\n\n// after: distinct values\n@Entity @DiscriminatorValue(\"A\") public class TypeA extends Base { }\n@Entity @DiscriminatorValue(\"B\") public class TypeB extends Base { }","handlingStrategy":"validation","validationCode":"// after Metadata build: assert discriminator-value uniqueness per hierarchy\nMap<String, String> seenByRoot = new HashMap<>();\nfor (PersistentClass pc : metadata.getEntityBindings()) {\n    Object v = pc.getDiscriminatorValue();\n    if (v == null) continue;\n    String key = pc.getRootClass().getEntityName() + \"::\" + String.valueOf(v).trim().toLowerCase(Locale.ROOT);\n    if (seenByRoot.put(key, pc.getEntityName()) != null) {\n        throw new IllegalStateException(\"Duplicate discriminator value \" + v + \" in \" + pc.getRootClass().getEntityName());\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Give every class in a hierarchy an explicit @DiscriminatorValue so collisions are visible in code review","Avoid values that differ only by case or whitespace","Run the uniqueness scan in CI so new subclasses cannot silently collide"],"tags":["hibernate","orm","single-table-inheritance","discriminator","duplicate-mapping"],"backgroundTag":"duplicate-discriminator-value","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}