hibernate/hibernate-orm · error · AnnotationException

Class '" + propertyHolder.getEntityName() + "' is annotated

Error message

Class '" + propertyHolder.getEntityName() + "' is annotated '@IdClass' and may not have a property annotated '@Version'

What it means

A class mapped with @IdClass must not declare a @Version property: version/optimistic-lock state belongs to the entity itself, not to the composite-id mirror class. PropertyBinder detects the situation while binding the id-class property mapper (isIdentifierMapper) and throws AnnotationException at bootstrap.

Source

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

				getMappedSuperclassOrNull( declaringClass,
						inheritanceStatePerClass, buildingContext );
		if ( mappedSuperclass != null ) {
			// Don't overwrite an existing version property
			if ( mappedSuperclass.getDeclaredVersion() == null ) {
				mappedSuperclass.setDeclaredVersion( property );
			}
		}
		else {
			//we know the property is on the actual entity
			rootClass.setDeclaredVersion( property );
		}

		rootClass.setOptimisticLockStyle( OptimisticLockStyle.VERSION );
	}

	private static void checkVersionProperty(PropertyHolder propertyHolder, boolean isIdentifierMapper) {
		if ( isIdentifierMapper ) {
			throw new AnnotationException( "Class '" + propertyHolder.getEntityName()
					+ "' is annotated '@IdClass' and may not have a property annotated '@Version'"
			);
		}
		if ( !( propertyHolder.getPersistentClass() instanceof RootClass ) ) {
			throw new AnnotationException( "Entity '" + propertyHolder.getEntityName()
					+ "' is a subclass in an entity class hierarchy and may not have a property annotated '@Version'" );
		}
		if ( !propertyHolder.isEntity() ) {
			throw new AnnotationException( "Embedded class '" + propertyHolder.getEntityName()
					+ "' may not have a property annotated '@Version'" );
		}
	}

	private AnnotatedColumns bindBasicOrComposite(
			PropertyHolder propertyHolder,
			Nullability nullability,
			PropertyData inferredData,
			EntityBinder entityBinder,

View on GitHub (pinned to fad1729dce)

Solutions

  1. Delete the @Version property from the @IdClass; keep only the id fields.
  2. Put @Version on the owning @Entity class instead (its root, per the related subclass check).

Example fix

// before
public class OrderLineId implements Serializable {
    private Long order;
    private Long line;
    @Version                 // rejected inside an @IdClass
    private int version;
}

// after
public class OrderLineId implements Serializable {
    private Long order;
    private Long line;
}
// and on the entity:
@Entity
@IdClass(OrderLineId.class)
public class OrderLine {
    @Id private Long order;
    @Id private Long line;
    @Version private int version;
}
Defensive patterns

Strategy: validation

Validate before calling

// Id classes must mirror only id fields — no @Version
for (Class<?> entity : annotatedClasses) {
    IdClass idClass = entity.getAnnotation(IdClass.class);
    if (idClass == null) continue;
    for (Field f : idClass.value().getDeclaredFields()) {
        if (f.isAnnotationPresent(Version.class)) {
            throw new IllegalStateException("@IdClass " + idClass.value().getName() + " contains @Version field " + f.getName());
        }
    }
}

Try / catch

try {
    SessionFactory sf = cfg.buildSessionFactory();
} catch (AnnotationException e) {
    throw new IllegalStateException("@IdClass contains forbidden property: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: An @IdClass class (e.g. OrderLineId) containing a field annotated @Version; usually the id-class was created by copying all fields from the entity, version included.

Common situations: Hand-written id classes cloned from the entity; introducing optimistic locking into a composite-key entity by adding @Version 'everywhere'; code generators that mirror all entity fields into the id class.

Related errors


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