diff --git a/hibernate-core/src/main/java/org/hibernate/LockMode.java b/hibernate-core/src/main/java/org/hibernate/LockMode.java index 11f500538f..3bd549c3a8 100644 --- a/hibernate-core/src/main/java/org/hibernate/LockMode.java +++ b/hibernate-core/src/main/java/org/hibernate/LockMode.java @@ -24,14 +24,15 @@ import jakarta.persistence.LockModeType; */ public enum LockMode { /** - * No lock required. If an object is requested with this lock - * mode, a {@link #READ} lock will be obtained if it is - * necessary to actually read the state from the database, + * No lock required. If an object is requested with this + * lock mode, a {@link #READ} lock will be obtained if it + * is necessary to actually read the state from the database, * rather than pull it from a cache. *
* This is the "default" lock mode. */ NONE( 0, "none" ), + /** * A shared lock. Objects in this lock mode were read from * the database in the current transaction, rather than being @@ -40,31 +41,34 @@ public enum LockMode { READ( 5, "read" ), /** - * Optimistically assume that transaction will not experience contention for - * entities. The entity version will be verified near the transaction end. + * Optimistically assume that transaction will not experience + * contention for an entity. The version will be verified near + * the transaction end. */ OPTIMISTIC( 6, "optimistic" ), /** - * Optimistically assume that transaction will not experience contention for - * entities. The entity version will be verified and incremented near the transaction end. + * Optimistically assume that transaction will not experience + * contention for an entity. The version will be verified and + * incremented near the transaction end. */ OPTIMISTIC_FORCE_INCREMENT( 7, "optimistic_force_increment" ), /** - * A {@code WRITE} lock is obtained when an object is updated or inserted. - * - * This lock mode is for internal use only and is not a valid mode for - * {@code load()} or {@code lock()}, both of which throw exceptions if - * {@code WRITE} is specified. + * A {@code WRITE} lock is obtained when an object is updated + * or inserted. + *
+ * This lock mode is for internal use only and is not a valid + * argument to {@code load()} or {@code lock()}. These method + * throw an exception if {@code WRITE} given as an argument. */ @Internal WRITE( 10, "write" ), /** * Attempt to obtain an upgrade lock, using an Oracle-style - * {@code select for update nowait}. The semantics of - * this lock mode, once obtained, are the same as + * {@code select for update nowait}. The semantics of this + * lock mode, once obtained, are the same as * {@link #PESSIMISTIC_WRITE}. */ UPGRADE_NOWAIT( 10, "upgrade-nowait" ), @@ -78,7 +82,7 @@ public enum LockMode { UPGRADE_SKIPLOCKED( 10, "upgrade-skiplocked" ), /** - * Implemented as PESSIMISTIC_WRITE. + * Implemented as {@link #PESSIMISTIC_WRITE}. */ PESSIMISTIC_READ( 12, "pessimistic_read" ), diff --git a/hibernate-core/src/main/java/org/hibernate/LockOptions.java b/hibernate-core/src/main/java/org/hibernate/LockOptions.java index a752502bb4..a5c085c22b 100644 --- a/hibernate-core/src/main/java/org/hibernate/LockOptions.java +++ b/hibernate-core/src/main/java/org/hibernate/LockOptions.java @@ -12,98 +12,130 @@ import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; +import java.util.Objects; +import jakarta.persistence.PessimisticLockScope; import org.hibernate.query.Query; +import org.hibernate.query.spi.QueryOptions; + +import static java.util.Collections.emptyList; /** - * Contains locking details (LockMode, Timeout and Scope). - * + * Contains a set of options describing how a row of a database table + * mapped by an entity should be locked. For + * {@link Session#buildLockRequest(LockOptions)}, + * {@link Session#get(Class, Object, LockOptions)}, or + * {@link Session#refresh(Object, LockOptions)}, the relevant options + * are: + *
+ * Differs from {@link #getEffectiveLockMode(String)} in that here we + * only return an explicitly specified alias-specific lock mode. * * @param alias The alias for which to locate the explicit lock mode. - * * @return The explicit lock mode for that alias. */ public LockMode getAliasSpecificLockMode(String alias) { - if ( aliasSpecificLockModes == null ) { - return null; - } - return aliasSpecificLockModes.get( alias ); + return aliasSpecificLockModes == null ? null : aliasSpecificLockModes.get( alias ); } /** - * Determine the {@link LockMode} to apply to the given alias. If no - * mode was explicitly {@linkplain #setAliasSpecificLockMode set}, the - * {@linkplain #getLockMode overall mode} is returned. If the overall - * lock mode is {@code null} as well, {@link LockMode#NONE} is returned. - *
- * Differs from {@link #getAliasSpecificLockMode} in that here we fallback to we only return - * the overall lock mode. + * Determine the {@link LockMode} to apply to the given alias. If no + * mode was {@linkplain #setAliasSpecificLockMode(String, LockMode)} + * explicitly set}, the {@linkplain #getLockMode()} overall mode} is + * returned. If the overall lock mode is also {@code null}, + * {@link LockMode#NONE} is returned. + *
+ * Differs from {@link #getAliasSpecificLockMode(String)} in that here
+ * we fall back to only returning the overall lock mode.
*
* @param alias The alias for which to locate the effective lock mode.
- *
* @return The effective lock mode.
*/
public LockMode getEffectiveLockMode(String alias) {
@@ -172,31 +200,31 @@ public class LockOptions implements Serializable {
}
/**
- * Does this {@code LockOptions} instance define alias-specific lock modes?
+ * Does this {@code LockOptions} instance define alias-specific lock
+ * modes?
*
- * @return {@code true} if this object defines alias-specific lock modes; {@code false} otherwise.
+ * @return {@code true} if this object defines alias-specific lock modes;
+ * {@code false} otherwise.
*/
public boolean hasAliasSpecificLockModes() {
return aliasSpecificLockModes != null
- && ! aliasSpecificLockModes.isEmpty();
+ && ! aliasSpecificLockModes.isEmpty();
}
/**
- * Get the number of aliases that have specific lock modes defined.
+ * The number of aliases that have alias-specific lock modes specified.
*
* @return the number of explicitly defined alias lock modes.
*/
public int getAliasLockCount() {
- if ( aliasSpecificLockModes == null ) {
- return 0;
- }
- return aliasSpecificLockModes.size();
+ return aliasSpecificLockModes == null ? 0 : aliasSpecificLockModes.size();
}
/**
- * Iterator for accessing Alias (key) and LockMode (value) as Map.Entry.
+ * Iterator over {@link Map.Entry}s, each containing an alias and its
+ * {@link LockMode}.
*
- * @return Iterator for accessing the Map.Entry's
+ * @return an iterator over the {@link Map.Entry}s
* @deprecated use {@link #getAliasSpecificLocks()}
*/
@Deprecated
@@ -205,15 +233,13 @@ public class LockOptions implements Serializable {
}
/**
- * Iterable access to alias (key) and LockMode (value) as Map.Entry.
+ * Iterable with {@link Map.Entry}s, each containing an alias and its
+ * {@link LockMode}.
*
- * @return Iterable for accessing the Map.Entry's
+ * @return an iterable with the {@link Map.Entry}s
*/
public Iterable
+ * {@link #NO_WAIT}, {@link #WAIT_FOREVER}, or {@link #SKIP_LOCKED}
+ * represent 3 "magic" values.
*
- * @return timeout in milliseconds, {@link #NO_WAIT}, {@link #WAIT_FOREVER} or {@link #SKIP_LOCKED}
+ * @return a timeout in milliseconds, {@link #NO_WAIT},
+ * {@link #WAIT_FOREVER}, or {@link #SKIP_LOCKED}
*/
public int getTimeOut() {
return timeout;
}
/**
- * Set the timeout setting.
- *
+ * {@link #NO_WAIT}, {@link #WAIT_FOREVER}, or {@link #SKIP_LOCKED}
+ * represent 3 "magic" values.
*
- * @param timeout The new timeout setting, in milliseconds
- *
- * @return this (for method chaining).
+ * @param timeout the new timeout setting, in milliseconds
+ * @return {@code this} for method chaining
*
* @see #getTimeOut
*/
@@ -270,44 +299,93 @@ public class LockOptions implements Serializable {
return this;
}
- private boolean scope;
+ /**
+ * The current lock scope:
+ *
+ * This strategy is valid for {@link LockMode#OPTIMISTIC_FORCE_INCREMENT}.
*
* @author Scott Marlow
* @since 3.5
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/OptimisticLockingStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/OptimisticLockingStrategy.java
index 68b927a35c..8a3eab98c5 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/lock/OptimisticLockingStrategy.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/OptimisticLockingStrategy.java
@@ -14,9 +14,10 @@ import org.hibernate.event.spi.EventSource;
import org.hibernate.persister.entity.Lockable;
/**
- * An optimistic locking strategy that verifies that the version hasn't changed (prior to transaction commit).
+ * An optimistic locking strategy that simply verifies that the
+ * version has not changed, just before committing the transaction.
*
+ * This strategy is valid for {@link LockMode#PESSIMISTIC_FORCE_INCREMENT}.
*
* @author Scott Marlow
* @since 3.5
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadSelectLockingStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadSelectLockingStrategy.java
index 6179f974ef..fd0650f6ef 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadSelectLockingStrategy.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadSelectLockingStrategy.java
@@ -23,14 +23,15 @@ import org.hibernate.sql.SimpleSelect;
import org.hibernate.stat.spi.StatisticsImplementor;
/**
- * A pessimistic locking strategy where the locks are obtained through select statements.
- *
+ * For non-read locks, this is achieved through the dialect's native
+ * {@code SELECT ... FOR UPDATE} syntax.
+ *
+ * This strategy is valid for {@link LockMode#PESSIMISTIC_READ}.
+ *
+ * This class is a clone of {@link SelectLockingStrategy}.
*
* @author Steve Ebersole
* @author Scott Marlow
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadUpdateLockingStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadUpdateLockingStrategy.java
index dc120d7ee2..3fc2f838e1 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadUpdateLockingStrategy.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadUpdateLockingStrategy.java
@@ -25,11 +25,12 @@ import org.hibernate.stat.spi.StatisticsImplementor;
import org.jboss.logging.Logger;
/**
- * A pessimistic locking strategy where the locks are obtained through update statements.
- *
+ * This strategy is valid for {@link LockMode#PESSIMISTIC_READ}.
+ *
+ * This class is a clone of {@link UpdateLockingStrategy}.
*
* @author Steve Ebersole
* @author Scott Marlow
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteSelectLockingStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteSelectLockingStrategy.java
index 3bafd8ac7c..4c9baa0cb7 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteSelectLockingStrategy.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteSelectLockingStrategy.java
@@ -23,14 +23,15 @@ import org.hibernate.sql.SimpleSelect;
import org.hibernate.stat.spi.StatisticsImplementor;
/**
- * A pessimistic locking strategy where the locks are obtained through select statements.
- *
+ * For non-read locks, this is achieved through the dialect's native
+ * {@code SELECT ... FOR UPDATE} syntax.
+ *
+ * This strategy is valid for {@link LockMode#PESSIMISTIC_WRITE}.
+ *
+ * This class is a clone of {@link SelectLockingStrategy}.
*
* @see org.hibernate.dialect.Dialect#getForUpdateString(LockMode)
* @see org.hibernate.dialect.Dialect#appendLockHint(LockOptions, String)
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteUpdateLockingStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteUpdateLockingStrategy.java
index b936b2f180..17e0309bcc 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteUpdateLockingStrategy.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteUpdateLockingStrategy.java
@@ -25,11 +25,12 @@ import org.hibernate.stat.spi.StatisticsImplementor;
import org.jboss.logging.Logger;
/**
- * A pessimistic locking strategy where the locks are obtained through update statements.
- *
+ * This strategy is valid for {@link LockMode#PESSIMISTIC_WRITE}.
+ *
+ * This class is a clone of {@link UpdateLockingStrategy}.
*
* @author Steve Ebersole
* @author Scott Marlow
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/SelectLockingStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/SelectLockingStrategy.java
index b3caf9e28c..7c33d660c7 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/lock/SelectLockingStrategy.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/SelectLockingStrategy.java
@@ -23,10 +23,10 @@ import org.hibernate.sql.SimpleSelect;
import org.hibernate.stat.spi.StatisticsImplementor;
/**
- * A locking strategy where the locks are obtained through select statements.
+ * A locking strategy where a lock is obtained via a select statement.
*
* This strategy is not valid for read style locks.
*
* @author Steve Ebersole
+ *
+ *
+ * @return the current {@link PessimisticLockScope}
+ */
+ public PessimisticLockScope getLockScope() {
+ return scope ? PessimisticLockScope.EXTENDED : PessimisticLockScope.NORMAL;
+ }
/**
- * Retrieve the current lock scope setting.
- *
- * "scope" is a JPA defined term. It is basically a cascading of the lock to associations.
+ * Set the lock scope:
+ *
+ *
*
- * @return true if locking will be extended to owned associations
+ * @param scope the new {@link PessimisticLockScope}
+ * @return {@code this} for method chaining
*/
+ public LockOptions setLockScope(PessimisticLockScope scope) {
+ return setScope(scope==PessimisticLockScope.EXTENDED);
+ }
+
+ /**
+ * The current lock scope setting:
+ *
+ *
+ *
+ * @return {@code true} if the lock extends to owned associations
+ *
+ * @deprecated use {@link #getLockScope()}
+ */
+ @Deprecated(since = "6.2")
public boolean getScope() {
return scope;
}
/**
- * Set the scope.
+ * Set the lock scope setting:
+ *
+ *
*
- * @param scope The new scope setting
+ * @param scope the new scope setting
+ * @return {@code this} for method chaining
*
- * @return this (for method chaining).
+ * @deprecated use {@link #setLockScope(PessimisticLockScope)}
*/
+ @Deprecated(since = "6.2")
public LockOptions setScope(boolean scope) {
this.scope = scope;
return this;
}
/**
- * Retrieve the current follow-on-locking setting.
+ * The current follow-on locking setting.
*
- * @return true if follow-on-locking is enabled
+ * @return {@code true} if follow-on locking is enabled
+ *
+ * @see org.hibernate.dialect.Dialect#useFollowOnLocking(String, QueryOptions)
*/
public Boolean getFollowOnLocking() {
return followOnLocking;
}
/**
- * Set the follow-on-locking setting.
- * @param followOnLocking The new follow-on-locking setting
- * @return this (for method chaining).
+ * Set the follow-on locking setting.
+ *
+ * @param followOnLocking The new follow-on locking setting
+ * @return {@code this} for method chaining
+ *
+ * @see org.hibernate.dialect.Dialect#useFollowOnLocking(String, QueryOptions)
*/
public LockOptions setFollowOnLocking(Boolean followOnLocking) {
this.followOnLocking = followOnLocking;
@@ -330,7 +408,8 @@ public class LockOptions implements Serializable {
}
/**
- * Perform a shallow copy.
+ * Copy the options in the first given instance of
+ * {@code LockOptions} to the second given instance.
*
* @param source Source for the copy (copied from)
* @param destination Destination for the copy (copied to)
@@ -349,40 +428,25 @@ public class LockOptions implements Serializable {
}
@Override
- public boolean equals(Object o) {
- if ( this == o ) {
+ public boolean equals(Object object) {
+ if ( this == object ) {
return true;
}
- if ( o == null || getClass() != o.getClass() ) {
+ else if ( !(object instanceof LockOptions) ) {
return false;
}
-
- LockOptions that = (LockOptions) o;
-
- if ( timeout != that.timeout ) {
- return false;
+ else {
+ final LockOptions that = (LockOptions) object;
+ return timeout == that.timeout
+ && scope == that.scope
+ && lockMode == that.lockMode
+ && Objects.equals( aliasSpecificLockModes, that.aliasSpecificLockModes )
+ && Objects.equals( followOnLocking, that.followOnLocking );
}
- if ( scope != that.scope ) {
- return false;
- }
- if ( lockMode != that.lockMode ) {
- return false;
- }
- if ( aliasSpecificLockModes != null ?
- !aliasSpecificLockModes.equals( that.aliasSpecificLockModes ) :
- that.aliasSpecificLockModes != null ) {
- return false;
- }
- return followOnLocking != null ? followOnLocking.equals( that.followOnLocking ) : that.followOnLocking == null;
}
@Override
public int hashCode() {
- int result = lockMode != null ? lockMode.hashCode() : 0;
- result = 31 * result + timeout;
- result = 31 * result + ( aliasSpecificLockModes != null ? aliasSpecificLockModes.hashCode() : 0 );
- result = 31 * result + ( followOnLocking != null ? followOnLocking.hashCode() : 0 );
- result = 31 * result + ( scope ? 1 : 0 );
- return result;
+ return Objects.hash( lockMode, timeout, aliasSpecificLockModes, followOnLocking, scope );
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/Session.java b/hibernate-core/src/main/java/org/hibernate/Session.java
index be3ed18b37..c3ead9a525 100644
--- a/hibernate-core/src/main/java/org/hibernate/Session.java
+++ b/hibernate-core/src/main/java/org/hibernate/Session.java
@@ -8,6 +8,7 @@ package org.hibernate;
import java.util.List;
+import jakarta.persistence.PessimisticLockScope;
import org.hibernate.graph.RootGraph;
import org.hibernate.query.Query;
import org.hibernate.stat.SessionStatistics;
@@ -1209,13 +1210,13 @@ public interface Session extends SharedSessionContract, EntityManager {
*/
interface LockRequest {
/**
- * Constant usable as a time out value that indicates no wait semantics should
+ * Constant usable as a timeout value indicating that no wait semantics should
* be used in attempting to acquire locks.
*/
int PESSIMISTIC_NO_WAIT = 0;
/**
- * Constant usable as a time out value that indicates that attempting to acquire
- * locks should be allowed to wait forever (apply no timeout).
+ * Constant usable as a timeout value indicating that attempting to acquire
+ * locks should be allowed to wait forever, that is, that there's no timeout.
*/
int PESSIMISTIC_WAIT_FOREVER = -1;
@@ -1243,9 +1244,10 @@ public interface Session extends SharedSessionContract, EntityManager {
int getTimeOut();
/**
- * Specify the pessimistic lock timeout. The default pessimistic lock behavior
- * is to wait forever for the lock. Lock timeout support is not available in
- * all {@link org.hibernate.dialect.Dialect SQL dialects}.
+ * Specify the pessimistic lock timeout. The default pessimistic lock
+ * behavior is to wait forever for the lock. Lock timeout support is
+ * not available in every {@link org.hibernate.dialect.Dialect dialect}
+ * of SQL.
*
* @param timeout is time in milliseconds to wait for lock.
* -1 means wait forever and 0 means no wait.
@@ -1255,24 +1257,43 @@ public interface Session extends SharedSessionContract, EntityManager {
LockRequest setTimeOut(int timeout);
/**
- * Check if locking is cascaded to owned collections and associated entities.
+ * Check if locking extends to owned collections and associated entities.
*
* @return true if locking will be extended to owned collections and associated entities
+ *
+ * @deprecated use {@link #getLockScope()}
*/
+ @Deprecated(since = "6.2")
boolean getScope();
/**
- * Specify whether the {@link LockMode} should be cascaded to owned collections
+ * Check if locking extends to owned collections and associated entities.
+ *
+ * @return true if locking will be extended to owned collections and associated entities
+ */
+ default PessimisticLockScope getLockScope() {
+ return getScope() ? PessimisticLockScope.EXTENDED : PessimisticLockScope.NORMAL;
+ }
+
+ /**
+ * Specify whether the {@link LockMode} should extend to owned collections
* and associated entities. An association must be mapped with
- * {@link org.hibernate.annotations.CascadeType#LOCK} for this setting to have
- * any effect.
+ * {@link org.hibernate.annotations.CascadeType#LOCK} for this setting to
+ * have any effect.
*
* @param scope {@code true} to cascade locks; {@code false} to not.
*
* @return {@code this}, for method chaining
+ *
+ * @deprecated use {@link #setLockScope(PessimisticLockScope)}
*/
+ @Deprecated(since = "6.2")
LockRequest setScope(boolean scope);
+ default LockRequest setLockScope(PessimisticLockScope scope) {
+ return setScope( scope == PessimisticLockScope.EXTENDED );
+ }
+
/**
* Perform the requested locking.
*
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java
index a22eda4471..0b7a8d47cc 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java
@@ -3258,7 +3258,7 @@ public abstract class Dialect implements ConversionContext {
}
/**
- * Get the UniqueDelegate supported by this dialect
+ * Get the {@link UniqueDelegate} supported by this dialect
*
* @return The UniqueDelegate
*/
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/OptimisticForceIncrementLockingStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/OptimisticForceIncrementLockingStrategy.java
index 103c046578..feec63a627 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/lock/OptimisticForceIncrementLockingStrategy.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/OptimisticForceIncrementLockingStrategy.java
@@ -15,10 +15,11 @@ import org.hibernate.event.spi.EventSource;
import org.hibernate.persister.entity.Lockable;
/**
- * An optimistic locking strategy that forces an increment of the version (after verifying that version hasn't changed).
- * This takes place just prior to transaction commit.
- *
- * This strategy is valid for LockMode.OPTIMISTIC_FORCE_INCREMENT
+ * An optimistic locking strategy that verifies that the version
+ * has not changed and then forces an increment of the version,
+ * just before committing the transaction.
+ *