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

  1. If the target really is an embeddable value, annotate the attribute @Embedded (single) or @ElementCollection (collection) alongside @TargetEmbeddable.
  2. If the target is an entity, remove @TargetEmbeddable and use @ManyToOne/@OneToOne with org.hibernate.annotations.@Target if you must pin the class.
  3. 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

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


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/24cb81c8e3ab2b1b. Report an issue: GitHub.