hibernate/hibernate-orm · error · AnnotationException
Property '${property}' is annotated '@OptimisticLock(exclude
Error message
Property '${property}' is annotated '@OptimisticLock(excluded=true)' and '@Id' What it means
@OptimisticLock(excluded = true) on the identifier property would exclude the id from optimistic-lock checks, which Hibernate forbids because identifier participation in locking is fixed by the mapping, not by this flag. PropertyBinder throws AnnotationException when it finds @Id together with excluded=true.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/internal/PropertyBinder.java:684
}
private void checkAnnotation(Class<? extends Annotation> annotationClass, Class<?> propertyType) {
if ( memberDetails.hasDirectAnnotationUsage( annotationClass )
&& !memberDetails.getType().isImplementor( propertyType ) ) {
throw new AnnotationException( "Property '" + qualify( holder.getPath(), name )
+ "' is annotated '@" + annotationClass.getSimpleName()
+ "' but is not of type '" + propertyType.getTypeName() + "'" );
}
}
private void validateOptimisticLock(boolean excluded) {
if ( excluded ) {
if ( isVersion( memberDetails ) ) {
throw new AnnotationException("Property '" + qualify( holder.getPath(), name )
+ "' is annotated '@OptimisticLock(excluded=true)' and '@Version'" );
}
if ( isSimpleId( memberDetails ) ) {
throw new AnnotationException("Property '" + qualify( holder.getPath(), name )
+ "' is annotated '@OptimisticLock(excluded=true)' and '@Id'" );
}
if ( isEmbeddedId( memberDetails ) ) {
throw new AnnotationException( "Property '" + qualify( holder.getPath(), name )
+ "' is annotated '@OptimisticLock(excluded=true)' and '@EmbeddedId'" );
}
}
}
/**
* @param elements List of {@link PropertyData} instances
* @param propertyContainer Metadata about a class and its properties
* @param idPropertyCounter number of id properties already present in list of {@link PropertyData} instances
*
* @return total number of id properties found after iterating the elements of {@code annotatedClass}
* using the determined access strategy (starting from the provided {@code idPropertyCounter})
*/
static int addElementsOfClass(View on GitHub (pinned to fad1729dce)
Solutions
- Remove @OptimisticLock(excluded = true) from the @Id property.
- Apply excluded=true only to genuinely lock-irrelevant mutable fields (e.g. audit counters, last-login timestamps).
Example fix
// before @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @OptimisticLock(excluded = true) private Long id; // after @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id;
Defensive patterns
Strategy: validation
Validate before calling
for (Class<?> entity : annotatedClasses) {
for (Field f : entity.getDeclaredFields()) {
OptimisticLock ol = f.getAnnotation(OptimisticLock.class);
if (ol != null && ol.excluded() && f.isAnnotationPresent(Id.class)) {
throw new IllegalStateException("@Id property may not use @OptimisticLock(excluded=true): " + f);
}
}
} Try / catch
try {
SessionFactory sf = cfg.buildSessionFactory();
} catch (AnnotationException e) {
throw new IllegalStateException("Optimistic-lock annotation conflict: " + e.getMessage(), e);
} Prevention
- Keep @OptimisticLock(excluded=true) off identifier fields
- Prefer applying the flag via careful review rather than bulk templates
When it happens
Trigger: A simple @Id property also annotated @OptimisticLock(excluded = true); typically an over-broad copy-paste of the exclusion flag onto every field of an entity.
Common situations: Applying @OptimisticLock(excluded=true) wholesale via code templates; attempting to reduce lock-scope overhead by excluding the id.
Related errors
- Property '${property}' is annotated '@OptimisticLock(exclude
- Property '${property}' is annotated '@OptimisticLock(exclude
- Attribute '" + memberDetails.getName() + "' is declared by '
- Attribute '${attribute}' is declared as an '@Id' or '@Embedd
- Member '" + memberDetails.getName() + "' of embeddable class
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/2881fc998e7f91d9.
Report an issue: GitHub.