hibernate/hibernate-orm · error · AnnotationException

Property '" + getPath( propertyHolder, inferredData ) + "' b

Error message

Property '" + getPath( propertyHolder, inferredData ) + "' belongs to an '@IdClass' and may not be annotated '@Id' or '@EmbeddedId'

What it means

Inside an @IdClass property mapper, none of the mirrored properties may themselves be annotated @Id or @EmbeddedId — the entity already declares the composite id via @Id fields plus @IdClass. PropertyBinder's generator handling throws AnnotationException when it finds an id annotation while binding in identifier-mapper mode.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/internal/PropertyBinder.java:1268

					memberDetails,
					actualColumns
			);
		}
		return this;
	}

	private void handleGenerators(
			PropertyHolder propertyHolder,
			PropertyData inferredData,
			boolean isIdentifierMapper,
			boolean isOverridden,
			PropertyData overridingProperty) {
		if ( isOverridden ) {
			handleGeneratorsForOverriddenId( propertyHolder, overridingProperty );
		}
		else if ( isId() ) {
			if ( isIdentifierMapper ) {
				throw new AnnotationException( "Property '" + getPath( propertyHolder, inferredData )
						+ "' belongs to an '@IdClass' and may not be annotated '@Id' or '@EmbeddedId'" );
			}
			//components and regular basic types create SimpleValue objects
			createIdGeneratorsFromGeneratorAnnotations(
					propertyHolder,
					inferredData,
					(SimpleValue) getValue(),
					buildingContext
			);
		}
	}

	private void aggregateBinder(
			PropertyHolder propertyHolder,
			PropertyData inferredData,
			EntityBinder entityBinder,
			boolean isIdentifierMapper,
			boolean isComponentEmbedded,

View on GitHub (pinned to fad1729dce)

Solutions

  1. Pick one composite-id style: either @IdClass with multiple @Id fields on the entity, or a single @EmbeddedId field — never both.
  2. Remove the offending @Id/@EmbeddedId annotation that reached the identifier mapper (usually the duplicated one).
  3. Verify the id class contains only plain fields matching the entity's @Id fields in name and type.

Example fix

// before: both composite-id styles mixed
@Entity
@IdClass(OrderLineId.class)
public class OrderLine {
    @Id private Long order;
    @Id private Long line;
    @EmbeddedId         // rejected: property already in the @IdClass mapper
    private OrderLineId id;
}

// after: single style
@Entity
@IdClass(OrderLineId.class)
public class OrderLine {
    @Id private Long order;
    @Id private Long line;
}
Defensive patterns

Strategy: validation

Validate before calling

// Don't mix @IdClass and @EmbeddedId on one entity
for (Class<?> entity : annotatedClasses) {
    boolean hasIdClass = entity.isAnnotationPresent(IdClass.class);
    boolean hasEmbeddedId = Arrays.stream(entity.getDeclaredFields())
            .anyMatch(f -> f.isAnnotationPresent(EmbeddedId.class));
    if (hasIdClass && hasEmbeddedId) {
        throw new IllegalStateException(entity.getName() + " mixes @IdClass and @EmbeddedId");
    }
}

Try / catch

try {
    SessionFactory sf = cfg.buildSessionFactory();
} catch (AnnotationException e) {
    throw new IllegalStateException("Composite id style conflict: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: An entity with @IdClass(OrderLineId.class) where the entity fields carry @Id AND the id-class side (or overridden/merged property data reaching the mapper) is re-annotated @Id/@EmbeddedId; typically double annotation after merging classes or misusing an @EmbeddedId field together with @IdClass.

Common situations: Mixing the two composite-id styles (@IdClass and @EmbeddedId) on one entity; copy-paste between an @EmbeddedId entity and an @IdClass entity; refactors where the id-class fields were copied back onto the entity with their annotations.

Related errors


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