hibernate/hibernate-orm · error · AnnotationPlacementException

@EmbeddedTable only supported for use on entity or mapped-su

Error message

@EmbeddedTable only supported for use on entity or mapped-superclass

What it means

@EmbeddedTable is a class-level annotation that only applies to entity classes and mapped superclasses. CollectionBinder.bind() throws this AnnotationPlacementException when it finds @EmbeddedTable placed directly on a collection property, because an embedded table cannot govern a collection attribute.

Source

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

	private Collection getCollection() {
		return collection;
	}

	private void setPropertyName(String propertyName) {
		this.propertyName = propertyName;
	}

	private void setDeclaringClass(ClassDetails declaringClass) {
		this.declaringClass = declaringClass;
		this.declaringClassSet = true;
	}

	private void bind() {
		if ( property != null ) {
			final EmbeddedTable misplaced = property.getDirectAnnotationUsage( EmbeddedTable.class );
			if ( misplaced != null ) {
				// not allowed
				throw new AnnotationPlacementException( "@EmbeddedTable only supported for use on entity or mapped-superclass" );
			}
		}
		collection = createCollection( propertyHolder.getPersistentClass() );
		final String role = qualify( propertyHolder.getPath(), propertyName );
		BOOT_LOGGER.bindingCollectionRole( role );
		collection.setRole( role );
		collection.setMappedByProperty( mappedBy );

		checkMapKeyColumn();
		//set laziness
		defineFetchingStrategy();
		collection.setMutable( isMutable() );
		//work on association
		final boolean isUnowned = isUnownedCollection();
		bindOptimisticLock( isUnowned );
		applySortingAndOrdering();
		bindCache();
		bindLoader();

View on GitHub (pinned to fad1729dce)

Solutions

  1. Remove @EmbeddedTable from the collection property
  2. Place @EmbeddedTable on the entity class or mapped superclass where it is supported
  3. For collections that need their own table, use @CollectionTable / @JoinTable instead

Example fix

// before
@Entity
public class Order {
    @EmbeddedTable(name = "order_extra")   // error: not allowed on a collection attribute
    @ElementCollection
    Set<String> tags;
}

// after
@Entity
@EmbeddedTable(name = "order_extra")      // class-level placement only
public class Order {
    @ElementCollection
    @CollectionTable(name = "order_tags",
        joinColumns = @JoinColumn(name = "order_id"))
    Set<String> tags;
}
Defensive patterns

Strategy: validation

Validate before calling

// Reject @EmbeddedTable placed on properties instead of classes
static void checkEmbeddedTablePlacement(Class<?>... entities) {
    for ( Class<?> c : entities ) {
        for ( Field f : c.getDeclaredFields() ) {
            if ( f.isAnnotationPresent( EmbeddedTable.class ) ) {
                throw new IllegalStateException( "@EmbeddedTable on property "
                    + c.getName() + "." + f.getName() + " (only class level is supported)" );
            }
        }
    }
}

Prevention

When it happens

Trigger: bind() runs for a collection property whose direct annotations include EmbeddedTable (property.getDirectAnnotationUsage(EmbeddedTable.class) != null).

Common situations: Adopting the @EmbeddedTable feature and annotating every mapped member 'just in case'; annotation auto-completion inserting @EmbeddedTable at field level; migrating from @SecondaryTable-style splits and placing the table hint on properties.

Related errors


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