hibernate/hibernate-orm · error · AnnotationException
Identifier field '{}' named in '@MapsId' does not exist in e
Error message
Identifier field '{}' named in '@MapsId' does not exist in entity '{}' What it means
'@MapsId("fieldName")' names an attribute that must be part of the entity's identifier — a field of an @EmbeddedId class or the simple/@IdClass id property. resolveMapsId() looked it up via persistentClass.getIdentifier()/getProperty(mapsId) and caught a MappingException because no such identifier attribute exists, so the derived-id mapping cannot be wired.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotatedJoinColumns.java:244
else {
for ( var joinColumn : joinColumns ) {
buildExplicitJoinTableJoinColumn( parent, propertyHolder, inferredData, joinColumn );
}
}
handlePropertyRef( inferredData.getAttributeMember(), parent );
return parent;
}
Property resolveMapsId() {
final var persistentClass = getPropertyHolder().getPersistentClass();
final var identifier = persistentClass.getIdentifier();
try {
return identifier instanceof Component embeddedIdType
? embeddedIdType.getProperty( mapsId ) // an @EmbeddedId
: persistentClass.getProperty( mapsId ); // a simple id or an @IdClass
}
catch (MappingException me) {
throw new AnnotationException( "Identifier field '" + mapsId
+ "' named in '@MapsId' does not exist in entity '" + persistentClass.getEntityName() + "'",
me );
}
}
public List<AnnotatedJoinColumn> getJoinColumns() {
return columns;
}
@Override
public void addColumn(AnnotatedColumn child) {
if ( !( child instanceof AnnotatedJoinColumn joinColumn ) ) {
throw new AssertionFailure( "wrong sort of column" );
}
addColumn( joinColumn );
}
public void addColumn(AnnotatedJoinColumn child) {View on GitHub (pinned to fad1729dce)
Solutions
- Match the @MapsId value EXACTLY (case-sensitive) to an attribute of the @EmbeddedId embeddable, or to the simple id property name.
- If the id is a simple @Id field, either omit the value ('@MapsId' with no argument) or use the id field's name.
- Re-run the bootstrap (test that builds a SessionFactory) after every rename of identifier fields.
Example fix
// before
@Embeddable
class OrderId implements Serializable {
Long number; // no 'id' field
}
@Entity
class Shipment {
@EmbeddedId OrderId id;
@ManyToOne(fetch = FetchType.LAZY)
@MapsId("id") // does not exist in OrderId
Order order;
}
// after
@Entity
class Shipment {
@EmbeddedId OrderId id;
@ManyToOne(fetch = FetchType.LAZY)
@MapsId("number")
Order order;
} Defensive patterns
Strategy: validation
Validate before calling
// Guard: @MapsId value must be a field of the embedded id (or the simple id)
for (Field f : cls.getDeclaredFields()) {
MapsId mapsId = f.getAnnotation(MapsId.class);
if (mapsId != null && !mapsId.value().isEmpty()) {
Field idField = cls.getDeclaredField("id");
Class<?> idType = idField.getType();
if (idType.isAnnotationPresent(Embeddable.class)
&& Arrays.stream(idType.getDeclaredFields())
.noneMatch(x -> x.getName().equals(mapsId.value()))) {
throw new IllegalStateException("@MapsId(" + mapsId.value()
+ ") is not an attribute of " + idType.getSimpleName());
}
}
} Try / catch
try {
Metadata md = sources.buildMetadata();
} catch (AnnotationException e) {
// 'Identifier field ... does not exist' -> fix the mapsId string to match the id attribute
throw newConfigurationException("Bad @MapsId target", e);
} Prevention
- Treat @MapsId values like stringly-typed references: update them in the same change-set as id field renames.
- For simple ids, prefer the no-arg '@MapsId' form.
- Assert one SessionFactory bootstrap test per persistence unit in CI.
When it happens
Trigger: '@MapsId("userId")' on an association when the entity's @EmbeddedId class has no 'userId' field; a typo or case mismatch in the mapsId value; using the Java field name of the association itself instead of the id attribute; @MapsId on an entity whose id is @GeneratedValue with a different property name.
Common situations: Renames during refactoring that change the embeddable's field but not the @MapsId string; switching between @IdClass and @EmbeddedId without updating mapsId values; following derived-id examples and mistaking the FK property for the id property.
Related errors
- Association '{}' in entity '{}' is annotated '@MapsId' but r
- Class '<componentClassName>' is an '@Embeddable' type and ma
- Property '<propertyName>' may not be annotated '@BatchSize'
- One to many association '<propertyName>' was annotated '@Col
- Collection '<propertyName>' was annotated '@Collate'
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/f061d6e36404528a.
Report an issue: GitHub.