{"record":{"id":"29e001d4deb4745f","repo":"hibernate/hibernate-orm","slug":"identifier-attribute-s-of-entity-s-has-type","errorCode":null,"errorMessage":"Identifier attribute '%s' of entity '%s' has type '%s' but is mapped by association '%s' to entity '%s' with composite identifier type '%s'","messagePattern":"Identifier attribute '(.+?)' of entity '(.+?)' has type '(.+?)' but is mapped by association '(.+?)' to entity '(.+?)' with composite identifier type '(.+?)'","errorType":"exception","errorClass":"AnnotationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/boot/model/internal/PropertyBinder.java","lineNumber":1525,"sourceCode":"\t\t\tInFlightMetadataCollector collector) {\n\t\tfinal var referencedEntityName = mapsIdProperty.getClassOrElementName();\n\t\tfinal var referencedEntityBinding = collector.getEntityBinding( referencedEntityName );\n\t\tif ( referencedEntityBinding != null ) {\n\t\t\tif ( referencedEntityBinding.getIdentifier() instanceof Component compositeId ) {\n\t\t\t\tif ( !isEmbeddedId( property ) ) {\n\t\t\t\t\tthrow new AnnotationException(\n\t\t\t\t\t\t\t\"Attribute '%s' of entity '%s' is mapped by association '%s' but is not annotated '@EmbeddedId'\"\n\t\t\t\t\t\t\t\t\t.formatted(\n\t\t\t\t\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t\t\t\t\t\tpropertyHolder.getPersistentClass().getEntityName(),\n\t\t\t\t\t\t\t\t\t\t\tmapsIdProperty.getPropertyName()\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tfinal String expectedTypeName = compositeId.getComponentClassName();\n\t\t\t\tfinal String actualTypeName = property.getType().getName();\n\t\t\t\tif ( !hasCompatibleType( actualTypeName, expectedTypeName ) ) {\n\t\t\t\t\tthrow new AnnotationException(\n\t\t\t\t\t\t\t\"Identifier attribute '%s' of entity '%s' has type '%s' but is mapped by association '%s' to entity '%s' with composite identifier type '%s'\"\n\t\t\t\t\t\t\t\t\t.formatted(\n\t\t\t\t\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t\t\t\t\t\tpropertyHolder.getPersistentClass().getEntityName(),\n\t\t\t\t\t\t\t\t\t\t\tactualTypeName,\n\t\t\t\t\t\t\t\t\t\t\tmapsIdProperty.getPropertyName(),\n\t\t\t\t\t\t\t\t\t\t\treferencedEntityName,\n\t\t\t\t\t\t\t\t\t\t\texpectedTypeName\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif ( !isSimpleId( property ) ) {\n\t\t\t\t\tthrow new AnnotationException(\n\t\t\t\t\t\t\t\"Attribute '%s' of entity '%s' is mapped by association '%s' but is not annotated '@Id'\"\n\t\t\t\t\t\t\t\t\t.formatted(\n\t\t\t\t\t\t\t\t\t\t\tpropertyName,","sourceCodeStart":1507,"sourceCodeEnd":1543,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/boot/model/internal/PropertyBinder.java#L1507-L1543","documentation":"Thrown when @MapsId references an entity with a composite @EmbeddedId and the dependent attribute is @EmbeddedId, but its Java type does not match the referenced entity's composite id class. checkMappedId compares property.getType().getName() with compositeId.getComponentClassName() via hasCompatibleType and rejects mismatches, printing expected vs actual type names.","triggerScenarios":"Parent uses @EmbeddedId ParentId; child declares @EmbeddedId with a hand-written ChildId class that duplicates the fields instead of reusing the parent's id class (or uses an unrelated embeddable). Fires only when the parent binding is registered and its identifier is a Component.","commonSituations":"Developers writing a 'local' embeddable for the child's composite key instead of reusing the parent's id class; refactoring the parent's id class to a new name while the child keeps the old one; code-generated id classes diverging between modules.","solutions":["Reuse the parent's embeddable id class as the child's @EmbeddedId type (or a compatible identical type per hasCompatibleType).","If the child truly needs extra key columns, put them in an embeddable that embeds the parent id type as a nested field and keep the mapped attribute's type aligned.","Alternatively abandon @MapsId and map the FK columns explicitly with @JoinColumn plus a separate id."],"exampleFix":"// before\n@Embeddable\npublic class ChildId implements Serializable {\n    private Long parentId; // duplicate of ParentId - type mismatch\n    private String extra;\n}\n\n@EmbeddedId\nprivate ChildId id;\n\n// after: reuse the parent's id type\n@Embeddable\npublic class ChildId implements Serializable {\n    @Embedded\n    private ParentId parentId; // same type as parent's @EmbeddedId\n    private String extra;\n}\n\n@EmbeddedId\nprivate ChildId id;\n\n@ManyToOne(fetch = FetchType.LAZY)\n@MapsId(\"parentId\")\nprivate Parent parent;","handlingStrategy":"validation","validationCode":"// assert child EmbeddedId type equals parent EmbeddedId type before bootstrap\nClass<?> parentIdType = parentIdEmbeddable(Parent.class); // e.g. ParentId\nClass<?> childIdType = childEmbeddedIdType(Child.class);\nif (!parentIdType.equals(childIdType)) {\n    throw new IllegalStateException(\"Child id type \" + childIdType.getName()\n        + \" must match parent's \" + parentIdType.getName());\n}","typeGuard":null,"tryCatchPattern":"try {\n    metadata = sources.buildMetadata();\n} catch (AnnotationException e) {\n    failBuild(\"MapsId type mismatch (expected vs actual in message): \" + e.getMessage());\n}","preventionTips":["Use the parent's id class directly as the child's EmbeddedId type.","Add a unit test comparing both id classes for every @MapsId pair.","Regenerate id classes from one shared source when code-generating."],"tags":["hibernate","orm","mapsid","embedded-id","type-mismatch","mapping"],"backgroundTag":"jpa-mapsid-misuse","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}