clarify some javadoc for @Immutable and optimistic locking stuff
This commit is contained in:
parent
3c535c544f
commit
bdc67f81b1
|
@ -13,13 +13,15 @@ import java.lang.annotation.RetentionPolicy;
|
||||||
import static java.lang.annotation.ElementType.*;
|
import static java.lang.annotation.ElementType.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks an entity, collection, or attribute as immutable. The absence of this annotation
|
* Marks an entity, collection, or attribute of an entity as immutable. The absence of this
|
||||||
* means the element is mutable.
|
* annotation means the element is mutable.
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>
|
* <li>
|
||||||
* Changes made in memory to the state of an immutable entity are never synchronized to
|
* Changes made in memory to the state of an immutable entity are never synchronized to
|
||||||
* the database. The changes are ignored, with no exception thrown. In a mapped inheritance
|
* the database. The changes are ignored, with no exception thrown. In a mapped inheritance
|
||||||
* hierarchy, {@code @Immutable} may be applied only to the root entity.
|
* hierarchy, {@code @Immutable} may be applied only to the root entity, and is inherited
|
||||||
|
* by entity subclasses. To make just one entity in the hierarchy immutable, annotate its
|
||||||
|
* attributes individually.
|
||||||
* </li>
|
* </li>
|
||||||
* <li>
|
* <li>
|
||||||
* An immutable collection may not be modified. A {@link org.hibernate.HibernateException}
|
* An immutable collection may not be modified. A {@link org.hibernate.HibernateException}
|
||||||
|
|
|
@ -12,11 +12,14 @@ import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies whether updating the annotated attribute should trigger an increment
|
* Specifies whether mutating the annotated attribute should trigger an increment
|
||||||
* to the {@link jakarta.persistence.Version version} of the entity instance.
|
* 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.
|
||||||
* <p>
|
* <p>
|
||||||
* If this annotation is not present, updating an attribute does cause the version
|
* If this annotation is not present, mutating an attribute <em>does</em> cause the
|
||||||
* to be incremented.
|
* version to be incremented.
|
||||||
*
|
*
|
||||||
* @author Logi Ragnarsson
|
* @author Logi Ragnarsson
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -14,7 +14,8 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies how optimistic lock checking works for the annotated entity.
|
* 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:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>the {@linkplain OptimisticLockType#VERSION version or timestamp},
|
* <li>the {@linkplain OptimisticLockType#VERSION version or timestamp},
|
||||||
* <li>the {@linkplain OptimisticLockType#DIRTY dirty fields} of the
|
* <li>the {@linkplain OptimisticLockType#DIRTY dirty fields} of the
|
||||||
|
@ -23,14 +24,22 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
* </ul>
|
* </ul>
|
||||||
* An optimistic lock is usually checked by including a restriction in a
|
* An optimistic lock is usually checked by including a restriction in a
|
||||||
* SQL {@code update} or {@code delete} statement. If the database reports
|
* SQL {@code update} or {@code delete} statement. If the database reports
|
||||||
* that zero rows were updated, we may infer that another transaction has
|
* that zero rows were updated, it is inferred that another transaction
|
||||||
* already updated or deleted the row, and report the {@linkplain
|
* has already updated or deleted the row, and the failure of the optimistic
|
||||||
* jakarta.persistence.OptimisticLockException failure} of the optimistic
|
* lock is reported via an {@link jakarta.persistence.OptimisticLockException}.
|
||||||
* lock.
|
|
||||||
* <p>
|
* <p>
|
||||||
* In an inheritance hierarchy, this annotation may only be applied to the
|
* In an inheritance hierarchy, this annotation may only be applied to the
|
||||||
* root entity, since the optimistic lock checking strategy is inherited
|
* root entity, since the optimistic lock checking strategy is inherited
|
||||||
* by entity subclasses.
|
* by entity subclasses.
|
||||||
|
* <p>
|
||||||
|
* To exclude a particular attribute from optimistic locking, annotate the
|
||||||
|
* attribute {@link OptimisticLock @OptimisticLock(excluded=true)}. Then:
|
||||||
|
* <ul>
|
||||||
|
* <li>changes to that attribute will never trigger a version increment, and
|
||||||
|
* <li>the attribute will not be included in the list of fields checked fields
|
||||||
|
* when {@link OptimisticLockType#ALL} or {@link OptimisticLockType#DIRTY}
|
||||||
|
* is used.
|
||||||
|
* </ul>
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*
|
*
|
||||||
|
|
|
@ -381,8 +381,8 @@ public class PropertyBinder {
|
||||||
return property;
|
return property;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleNaturalId(Property prop) {
|
private void handleNaturalId(Property property) {
|
||||||
final NaturalId naturalId = property.getAnnotation(NaturalId.class);
|
final NaturalId naturalId = this.property.getAnnotation(NaturalId.class);
|
||||||
if ( naturalId != null ) {
|
if ( naturalId != null ) {
|
||||||
if ( !entityBinder.isRootEntity() ) {
|
if ( !entityBinder.isRootEntity() ) {
|
||||||
throw new AnnotationException( "Property '" + qualify( holder.getPath(), name )
|
throw new AnnotationException( "Property '" + qualify( holder.getPath(), name )
|
||||||
|
@ -392,27 +392,27 @@ public class PropertyBinder {
|
||||||
if ( !naturalId.mutable() ) {
|
if ( !naturalId.mutable() ) {
|
||||||
updatable = false;
|
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...
|
// this is already handled for collections in CollectionBinder...
|
||||||
if ( value instanceof Collection ) {
|
if ( value instanceof Collection ) {
|
||||||
prop.setOptimisticLocked( ((Collection) value).isOptimisticLocked() );
|
property.setOptimisticLocked( ((Collection) value).isOptimisticLocked() );
|
||||||
}
|
}
|
||||||
else if ( property != null && property.isAnnotationPresent(OptimisticLock.class) ) {
|
else if ( this.property != null && this.property.isAnnotationPresent(OptimisticLock.class) ) {
|
||||||
final OptimisticLock lockAnn = property.getAnnotation(OptimisticLock.class);
|
final OptimisticLock optimisticLock = this.property.getAnnotation(OptimisticLock.class);
|
||||||
validateOptimisticLock(lockAnn);
|
validateOptimisticLock( optimisticLock );
|
||||||
prop.setOptimisticLocked( !lockAnn.excluded() );
|
property.setOptimisticLocked( !optimisticLock.excluded() );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
prop.setOptimisticLocked( !isToOneValue(value) || insertable ); // && updatable as well???
|
property.setOptimisticLocked( !isToOneValue(value) || insertable ); // && updatable as well???
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateOptimisticLock(OptimisticLock lockAnn) {
|
private void validateOptimisticLock(OptimisticLock optimisticLock) {
|
||||||
if ( lockAnn.excluded() ) {
|
if ( optimisticLock.excluded() ) {
|
||||||
if ( property.isAnnotationPresent(Version.class) ) {
|
if ( property.isAnnotationPresent(Version.class) ) {
|
||||||
throw new AnnotationException("Property '" + qualify( holder.getPath(), name )
|
throw new AnnotationException("Property '" + qualify( holder.getPath(), name )
|
||||||
+ "' is annotated '@OptimisticLock(excluded=true)' and '@Version'" );
|
+ "' is annotated '@OptimisticLock(excluded=true)' and '@Version'" );
|
||||||
|
|
Loading…
Reference in New Issue