hibernate/hibernate-orm · error · AnnotationException

Property '{}' belongs to an '@Embeddable' class that is cont

Error message

Property '{}' belongs to an '@Embeddable' class that is contained in an '@ElementCollection' and may not be a {}

What it means

JPA forbids nested collection associations: an @Embeddable used as the element of an @ElementCollection may not itself declare @OneToMany, @ManyToMany, or @ElementCollection properties. CollectionBinder.checkAnnotations throws this AnnotationException, naming the offending annotation, because there is no valid mapping for a collection nested inside a collection element.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/internal/CollectionBinder.java:434

	}

	private static PropertyData virtualPropertyData(PropertyData inferredData, MemberDetails property) {
		//do not use "element" if you are a JPA 2 @ElementCollection, only for legacy Hibernate mappings
		return property.hasDirectAnnotationUsage( ElementCollection.class )
				? inferredData
				: new WrappedInferredData(inferredData, "element" );
	}

	private static void checkAnnotations(
			PropertyHolder propertyHolder,
			PropertyData inferredData,
			MemberDetails property,
			OneToMany oneToMany,
			ManyToMany manyToMany,
			ElementCollection elementCollection) {
		if ( ( oneToMany != null || manyToMany != null || elementCollection != null )
				&& isToManyAssociationWithinEmbeddableCollection( propertyHolder ) ) {
			throw new AnnotationException( "Property '" + getPath( propertyHolder, inferredData ) +
					"' belongs to an '@Embeddable' class that is contained in an '@ElementCollection' and may not be a "
					+ annotationName( oneToMany, manyToMany, elementCollection ));
		}

		if ( oneToMany != null && property.hasDirectAnnotationUsage( SoftDelete.class ) ) {
			throw new UnsupportedMappingException(
					"@SoftDelete cannot be applied to @OneToMany - " +
							property.getDeclaringType().getName() + "." + property.getName()
			);
		}

		if ( property.hasDirectAnnotationUsage( OrderColumn.class )
				&& manyToMany != null
				&& isNotBlank( manyToMany.mappedBy() ) ) {
			throw new AnnotationException("Collection '" + getPath( propertyHolder, inferredData ) +
					"' is the unowned side of a bidirectional '@ManyToMany' and may not have an '@OrderColumn'");
		}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Promote the nested association to the owning entity: put the @OneToMany directly on the entity instead of inside the embeddable
  2. Model the nested data as a separate @Entity linked by a normal association from the owner
  3. Flatten the embeddable: remove the collection property and store repeated values through a real entity or a JSON column

Example fix

// before
@Entity
class Customer {
    @ElementCollection
    Set<Address> addresses;   // Address is @Embeddable
}
@Embeddable
class Address {
    @OneToMany(mappedBy = "address")   // error: nested to-many inside element-collection embeddable
    List<Phone> phones;
}

// after
@Entity
class Customer {
    @ElementCollection
    Set<Address> addresses;

    @OneToMany(mappedBy = "customer")   // association lives on the owning entity
    List<Phone> phones;
}
Defensive patterns

Strategy: validation

Validate before calling

// Reject to-many/@ElementCollection properties inside embeddables used as element-collection elements
static void checkNoNestedCollections(Class<?> entity, Class<? extends Annotation> elementAnn,
                                     Class<?> embeddable) {
    if ( entity.isAnnotationPresent( elementAnn ) ) {
        for ( Field f : embeddable.getDeclaredFields() ) {
            if ( f.isAnnotationPresent( OneToMany.class )
                    || f.isAnnotationPresent( ManyToMany.class )
                    || f.isAnnotationPresent( ElementCollection.class ) ) {
                throw new IllegalStateException( "Nested collection inside element-collection embeddable: "
                    + embeddable.getName() + "." + f.getName() );
            }
        }
    }
}

Prevention

When it happens

Trigger: An entity has an @ElementCollection of an @Embeddable type (or the property holder is otherwise within an embeddable collection), and a property of that embeddable carries @OneToMany, @ManyToMany, or @ElementCollection.

Common situations: Modeling nested collections like Order -> @ElementCollection Set<Address> -> List<Phone> inside Address; refactoring that moves an association into an embeddable that is also used as an element-collection element; reusing an embeddable in two contexts, one of which is an element collection.

Related errors


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