* An immutable collection may not be modified. A {@link org.hibernate.HibernateException}
diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/OptimisticLock.java b/hibernate-core/src/main/java/org/hibernate/annotations/OptimisticLock.java
index 2be58ebbe4..1a7d4bd5aa 100644
--- a/hibernate-core/src/main/java/org/hibernate/annotations/OptimisticLock.java
+++ b/hibernate-core/src/main/java/org/hibernate/annotations/OptimisticLock.java
@@ -12,11 +12,14 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
- * Specifies whether updating the annotated attribute should trigger an increment
- * to the {@link jakarta.persistence.Version version} of the entity instance.
+ * Specifies whether mutating the annotated attribute should trigger an increment
+ * to the {@link jakarta.persistence.Version version} of the entity instance. Or,
+ * if {@link OptimisticLockType#ALL} or {@link OptimisticLockType#DIRTY} are used,
+ * specifies whether the attribute should be included or excluded from the list of
+ * checked attributes.
*
- * If this annotation is not present, updating an attribute does cause the version
- * to be incremented.
+ * If this annotation is not present, mutating an attribute does cause the
+ * version to be incremented.
*
* @author Logi Ragnarsson
*/
diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/OptimisticLocking.java b/hibernate-core/src/main/java/org/hibernate/annotations/OptimisticLocking.java
index 91ff839495..d0a769aabb 100644
--- a/hibernate-core/src/main/java/org/hibernate/annotations/OptimisticLocking.java
+++ b/hibernate-core/src/main/java/org/hibernate/annotations/OptimisticLocking.java
@@ -14,7 +14,8 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Specifies how optimistic lock checking works for the annotated entity.
- * We may detect that an optimistic lock has failed by checking either:
+ * Optimistic lock checking may detect that an optimistic lock has failed,
+ * and that the transaction should be aborted, by comparing either:
*
* - the {@linkplain OptimisticLockType#VERSION version or timestamp},
*
- the {@linkplain OptimisticLockType#DIRTY dirty fields} of the
@@ -23,14 +24,22 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
*
* An optimistic lock is usually checked by including a restriction in a
* SQL {@code update} or {@code delete} statement. If the database reports
- * that zero rows were updated, we may infer that another transaction has
- * already updated or deleted the row, and report the {@linkplain
- * jakarta.persistence.OptimisticLockException failure} of the optimistic
- * lock.
+ * that zero rows were updated, it is inferred that another transaction
+ * has already updated or deleted the row, and the failure of the optimistic
+ * lock is reported via an {@link jakarta.persistence.OptimisticLockException}.
*
* In an inheritance hierarchy, this annotation may only be applied to the
* root entity, since the optimistic lock checking strategy is inherited
* by entity subclasses.
+ *
+ * To exclude a particular attribute from optimistic locking, annotate the
+ * attribute {@link OptimisticLock @OptimisticLock(excluded=true)}. Then:
+ *
+ * - changes to that attribute will never trigger a version increment, and
+ *
- the attribute will not be included in the list of fields checked fields
+ * when {@link OptimisticLockType#ALL} or {@link OptimisticLockType#DIRTY}
+ * is used.
+ *
*
* @author Steve Ebersole
*
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/PropertyBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/PropertyBinder.java
index 453b44e62a..01808b4510 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/PropertyBinder.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/PropertyBinder.java
@@ -381,8 +381,8 @@ public class PropertyBinder {
return property;
}
- private void handleNaturalId(Property prop) {
- final NaturalId naturalId = property.getAnnotation(NaturalId.class);
+ private void handleNaturalId(Property property) {
+ final NaturalId naturalId = this.property.getAnnotation(NaturalId.class);
if ( naturalId != null ) {
if ( !entityBinder.isRootEntity() ) {
throw new AnnotationException( "Property '" + qualify( holder.getPath(), name )
@@ -392,27 +392,27 @@ public class PropertyBinder {
if ( !naturalId.mutable() ) {
updatable = false;
}
- prop.setNaturalIdentifier( true );
+ property.setNaturalIdentifier( true );
}
}
- private void inferOptimisticLocking(Property prop) {
+ private void inferOptimisticLocking(Property property) {
// this is already handled for collections in CollectionBinder...
if ( value instanceof Collection ) {
- prop.setOptimisticLocked( ((Collection) value).isOptimisticLocked() );
+ property.setOptimisticLocked( ((Collection) value).isOptimisticLocked() );
}
- else if ( property != null && property.isAnnotationPresent(OptimisticLock.class) ) {
- final OptimisticLock lockAnn = property.getAnnotation(OptimisticLock.class);
- validateOptimisticLock(lockAnn);
- prop.setOptimisticLocked( !lockAnn.excluded() );
+ else if ( this.property != null && this.property.isAnnotationPresent(OptimisticLock.class) ) {
+ final OptimisticLock optimisticLock = this.property.getAnnotation(OptimisticLock.class);
+ validateOptimisticLock( optimisticLock );
+ property.setOptimisticLocked( !optimisticLock.excluded() );
}
else {
- prop.setOptimisticLocked( !isToOneValue(value) || insertable ); // && updatable as well???
+ property.setOptimisticLocked( !isToOneValue(value) || insertable ); // && updatable as well???
}
}
- private void validateOptimisticLock(OptimisticLock lockAnn) {
- if ( lockAnn.excluded() ) {
+ private void validateOptimisticLock(OptimisticLock optimisticLock) {
+ if ( optimisticLock.excluded() ) {
if ( property.isAnnotationPresent(Version.class) ) {
throw new AnnotationException("Property '" + qualify( holder.getPath(), name )
+ "' is annotated '@OptimisticLock(excluded=true)' and '@Version'" );