hibernate/hibernate-orm · error · MappingException
@TargetEmbeddable can only be specified on properties marked
Error message
@TargetEmbeddable can only be specified on properties marked with @Embedded or @ElementCollection [%s$%s]
What it means
@TargetEmbeddable names the embeddable implementation for an attribute; PropertyInferredData.getTargetEmbeddableAnnotation accepts it only when the member itself also carries @Embedded or @ElementCollection (a @ElementCollection member is trusted without deep-checking its component type). Anything else — association, plain field, meta-annotated member — throws a MappingException formatted as declaringType$memberName during property inference.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/internal/PropertyInferredData.java:117
if ( targetEmbeddable != null ) {
return resolveTargetEmbeddableAnnotation( targetEmbeddable, sourceModelContext );
}
return propertyMember.resolveRelativeType( ownerType );
}
private static TargetEmbeddable getTargetEmbeddableAnnotation(MemberDetails memberDetails) {
// first we look for the annotation on the member itself
final var memberAnnotation = memberDetails.getDirectAnnotationUsage( TargetEmbeddable.class );
if ( memberAnnotation != null ) {
// this should only be allowed for embedded or collections-of-embeddables.
// NOTE: this is tricky to check for collections-of-embeddables as it
// would require a deep check of the collection's component type, so
// for now just assume the mapping is correct if we find @ElementCollection
final boolean allowed = memberDetails.hasDirectAnnotationUsage( Embedded.class )
|| memberDetails.hasDirectAnnotationUsage( ElementCollection.class );
if ( !allowed ) {
throw new MappingException(
String.format(
Locale.ROOT,
"@TargetEmbeddable can only be specified on properties marked with @Embedded or @ElementCollection [%s$%s]",
memberDetails.getDeclaringType().getName(),
memberDetails.getName()
)
);
}
return memberAnnotation;
}
// then, look on the member's type
// NOTE: this is not supported for collections-of-embeddables
// for the same reason stated above
ClassDetails memberRawClass = memberDetails.getAssociatedType().determineRawClass();
if (memberRawClass.isJdkClass()) {
return null;View on GitHub (pinned to fad1729dce)
Solutions
- If the target really is an embeddable value, annotate the attribute @Embedded (single) or @ElementCollection (collection) alongside @TargetEmbeddable.
- If the target is an entity, remove @TargetEmbeddable and use @ManyToOne/@OneToOne with org.hibernate.annotations.@Target if you must pin the class.
- If the collection holds embeddables, switch @OneToMany to @ElementCollection + @CollectionTable.
Example fix
// before @TargetEmbeddable(Address.class) @ManyToOne private Address address; // Address is an @Embeddable, not an entity // after @TargetEmbeddable(Address.class) @Embedded private Address address;
Defensive patterns
Strategy: validation
Validate before calling
// verify @TargetEmbeddable is paired with @Embedded or @ElementCollection
for (Field f : Order.class.getDeclaredFields()) {
if (f.isAnnotationPresent(TargetEmbeddable.class)
&& !f.isAnnotationPresent(Embedded.class)
&& !f.isAnnotationPresent(ElementCollection.class)) {
throw new IllegalStateException("@TargetEmbeddable on non-embedded member: " + f);
}
} Try / catch
try {
metadata = sources.buildMetadata();
} catch (MappingException e) {
failBuild("Bad @TargetEmbeddable usage: " + e.getMessage());
} Prevention
- Use @TargetEmbeddable only with @Embedded/@ElementCollection; use @Target for entity associations.
- Keep a style rule that embeddable targets are declared right next to the embed annotations.
When it happens
Trigger: Placing @TargetEmbeddable(Address.class) on a @ManyToOne, @OneToOne without @Embedded, a @OneToMany collection of embeddables (not @ElementCollection), or a plain unannotated field. Thrown while Hibernate infers the property type from the member during binding.
Common situations: Confusing @TargetEmbeddable with org.hibernate.annotations.@Target (the latter is for entity association targets); annotating @OneToMany List<Line> with @TargetEmbeddable instead of @ElementCollection; copying the annotation to an association when refactoring an embeddable into an entity.
Related errors
- collection id mapping has wrong number of columns: " + getRo
- collection index mapping has wrong number of columns: " + ge
- Basic collection has element type '%s' which is not a known
- Unsupported attempt to resolve JDBC type for Map.Entry
- Error transforming element-collection :
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/24cb81c8e3ab2b1b.
Report an issue: GitHub.