HHH-15680 deprecate LockRequest and add overloads of lock() which accept LockOptions

This commit is contained in:
Gavin King 2022-11-07 10:40:23 +01:00
parent 4b7fcb5123
commit 61294250b3
5 changed files with 133 additions and 47 deletions

View File

@ -7,7 +7,6 @@
package org.hibernate;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
@ -23,7 +22,7 @@ import static java.util.Collections.emptyList;
/**
* 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#lock(Object, LockOptions)},
* {@link Session#get(Class, Object, LockOptions)}, or
* {@link Session#refresh(Object, LockOptions)}, the relevant options
* are:
@ -33,6 +32,10 @@ import static java.util.Collections.emptyList;
* <li>the {@link #getLockScope() lock scope}, that is, whether the
* lock extends to rows of owned collections.
* </ul>
* Timeout and lock scope are ignored if the specified {@code LockMode}
* represents a flavor of {@linkplain LockMode#OPTIMISTIC optimistic}
* locking.
* <p>
* In HQL and criteria queries, lock modes can be defined in an even
* more granular fashion, with the option to specify a lock mode that
* {@linkplain #setAliasSpecificLockMode(String, LockMode) applies
@ -42,13 +45,13 @@ import static java.util.Collections.emptyList;
*/
public class LockOptions implements Serializable {
/**
* Represents {@link LockMode#NONE}, where timeout and scope are
* Represents {@link LockMode#NONE}, to which timeout and scope are
* not applicable.
*/
public static final LockOptions NONE = new LockOptions(LockMode.NONE);
/**
* Represents {@link LockMode#READ}, where timeout and scope are
* Represents {@link LockMode#READ}, to which timeout and scope are
* not applicable.
*/
public static final LockOptions READ = new LockOptions(LockMode.READ);
@ -70,7 +73,9 @@ public class LockOptions implements Serializable {
public static final int NO_WAIT = 0;
/**
* Indicates that there is no timeout for the lock acquisition.
* Indicates that there is no timeout for the lock acquisition,
* that is, that the database should in principle wait forever
* to obtain the lock.
*
* @see #getTimeOut
*/
@ -92,14 +97,15 @@ public class LockOptions implements Serializable {
private Boolean followOnLocking;
/**
* Constructs an instance with all default options.
* Construct an instance with mode {@link LockMode#NONE} and
* timeout {@link #WAIT_FOREVER}.
*/
public LockOptions() {
}
/**
* Constructs an instance with the given {@linkplain LockMode
* lock mode}.
* Construct an instance with the given {@linkplain LockMode mode}
* and {@link #WAIT_FOREVER}.
*
* @param lockMode The lock mode to use
*/
@ -107,6 +113,29 @@ public class LockOptions implements Serializable {
this.lockMode = lockMode;
}
/**
* Construct an instance with the given {@linkplain LockMode mode}
* and timeout.
*
* @param lockMode The lock mode to use
*/
public LockOptions(LockMode lockMode, int timeout) {
this.lockMode = lockMode;
this.timeout = timeout;
}
/**
* Construct an instance with the given {@linkplain LockMode mode},
* timeout, and {@link PessimisticLockScope scope}.
*
* @param lockMode The lock mode to use
*/
public LockOptions(LockMode lockMode, int timeout, PessimisticLockScope scope) {
this.lockMode = lockMode;
this.timeout = timeout;
this.scope = scope == PessimisticLockScope.EXTENDED;
}
/**
* Determine of the lock options are empty.
*

View File

@ -651,68 +651,82 @@ public interface Session extends SharedSessionContract, EntityManager {
void delete(String entityName, Object object);
/**
* Obtain the specified lock level on the given managed instance association with
* this session. This may be used to:
* Obtain the specified lock level on the given managed instance associated
* with this session. This may be used to:
* <ul>
* <li>perform a version check with {@link LockMode#READ}, or
* <li>upgrade to a pessimistic lock with {@link LockMode#PESSIMISTIC_WRITE}).
* </ul>
* This operation cascades to associated instances if the association is mapped
* with {@link org.hibernate.annotations.CascadeType#LOCK}.
* <p>
* Convenient form of {@link LockRequest#lock(Object)} via
* {@link #buildLockRequest(LockOptions)}
* This operation cascades to associated instances if the association is
* mapped with {@link org.hibernate.annotations.CascadeType#LOCK}.
*
* @param object a persistent or transient instance
* @param lockMode the lock level
*
* @see #buildLockRequest(LockOptions)
* @see LockRequest#lock(Object)
*/
void lock(Object object, LockMode lockMode);
/**
* Obtain the specified lock level on the given managed instance association with
* this session. This may be used to:
* Obtain a lock on the given managed instance associated with this session,
* using the given {@link LockOptions lock options}.
* <p>
* This operation cascades to associated instances if the association is
* mapped with {@link org.hibernate.annotations.CascadeType#LOCK}.
*
* @param object a persistent or transient instance
* @param lockOptions the lock options
*/
void lock(Object object, LockOptions lockOptions);
/**
* Obtain the specified lock level on the given managed instance associated
* with this session. This may be used to:
* <ul>
* <li>perform a version check with {@link LockMode#READ}, or
* <li>upgrade to a pessimistic lock with {@link LockMode#PESSIMISTIC_WRITE}).
* </ul>
* This operation cascades to associated instances if the association is mapped
* with {@link org.hibernate.annotations.CascadeType#LOCK}.
* <p>
* Convenient form of {@link LockRequest#lock(String, Object)} via
* {@link #buildLockRequest(LockOptions)}
* This operation cascades to associated instances if the association is
* mapped with {@link org.hibernate.annotations.CascadeType#LOCK}.
*
* @param entityName the name of the entity
* @param object a persistent or transient instance
* @param lockMode the lock level
*
* @see #buildLockRequest(LockOptions)
* @see LockRequest#lock(String, Object)
*/
void lock(String entityName, Object object, LockMode lockMode);
/**
* Obtain a lock on the given managed instance associated with this session,
* using the given {@link LockOptions lock options}.
* <p>
* This operation cascades to associated instances if the association is
* mapped with {@link org.hibernate.annotations.CascadeType#LOCK}.
*
* @param entityName the name of the entity
* @param lockOptions the lock options
*/
void lock(String entityName, Object object, LockOptions lockOptions);
/**
* Build a new {@link LockRequest lock request} that specifies:
* <ul>
* <li>the {@link LockMode} to use,
* <li>the pessimistic lock timeout, and
* <li>the {@linkplain LockRequest#setScope(boolean) scope} of the lock.
* <li>the {@linkplain LockRequest#setTimeOut(int) pessimistic lock timeout},
* and
* <li>the {@linkplain LockRequest#setLockScope(PessimisticLockScope) scope}
* that is, whether the lock extends to rows of owned collections.
* </ul>
* Timeout and scope are ignored if the specified {@code LockMode} represents a
* form of {@linkplain LockMode#OPTIMISTIC optimistic} locking.
* Timeout and scope are ignored if the specified {@code LockMode} represents
* a flavor of {@linkplain LockMode#OPTIMISTIC optimistic} locking.
* <p>
* Call {@link LockRequest#lock(Object)} to actually obtain the requested lock
* on a managed entity instance.
* <p>
* Example usage:
* {@code session.buildLockRequest().setLockMode(LockMode.PESSIMISTIC_WRITE).setTimeOut(60000).lock(entity);}
*
* @param lockOptions contains the lock level
*
* @return a {@link LockRequest} that can be used to lock any given object.
*
* @deprecated use {@link #lock(Object, LockOptions)}
*/
@Deprecated(since = "6.2")
LockRequest buildLockRequest(LockOptions lockOptions);
/**
@ -720,8 +734,10 @@ public interface Session extends SharedSessionContract, EntityManager {
* from the underlying database. This may be useful:
* <ul>
* <li>when a database trigger alters the object state upon insert or update
* <li>after {@linkplain #createMutationQuery(String) executing} any HQL update or delete statement
* <li>after {@linkplain #createNativeMutationQuery(String) executing} a native SQL statement
* <li>after {@linkplain #createMutationQuery(String) executing} any HQL update
* or delete statement
* <li>after {@linkplain #createNativeMutationQuery(String) executing} a native
* SQL statement
* <li>after inserting a {@link java.sql.Blob} or {@link java.sql.Clob}
* </ul>
* This operation cascades to associated instances if the association is mapped
@ -736,8 +752,10 @@ public interface Session extends SharedSessionContract, EntityManager {
* from the underlying database. This may be useful:
* <ul>
* <li>when a database trigger alters the object state upon insert or update
* <li>after {@linkplain #createMutationQuery(String) executing} any HQL update or delete statement
* <li>after {@linkplain #createNativeMutationQuery(String) executing} a native SQL statement
* <li>after {@linkplain #createMutationQuery(String) executing} any HQL update
* or delete statement
* <li>after {@linkplain #createNativeMutationQuery(String) executing} a native
* SQL statement
* <li>after inserting a {@link java.sql.Blob} or {@link java.sql.Clob}
* </ul>
* This operation cascades to associated instances if the association is mapped
@ -1206,19 +1224,26 @@ public interface Session extends SharedSessionContract, EntityManager {
SharedSessionBuilder sessionWithOptions();
/**
* Contains locking details (LockMode, Timeout and Scope).
* A set of {@linkplain LockOptions locking options} attached
* to the session.
*
* @deprecated simply construct a {@link LockOptions} and pass
* it to {@link #lock(Object, LockOptions)}.
*/
@Deprecated(since = "6.2")
interface LockRequest {
/**
* Constant usable as a timeout value indicating that no wait semantics should
* be used in attempting to acquire locks.
* A timeout value indicating that the database should not
* wait at all to acquire a pessimistic lock which is not
* immediately available.
*/
int PESSIMISTIC_NO_WAIT = 0;
int PESSIMISTIC_NO_WAIT = LockOptions.NO_WAIT;
/**
* 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.
* A timeout value indicating that attempting to acquire
* that there is no timeout for the lock acquisition.
*/
int PESSIMISTIC_WAIT_FOREVER = -1;
int PESSIMISTIC_WAIT_FOREVER = LockOptions.WAIT_FOREVER;
/**
* Get the lock mode.

View File

@ -882,6 +882,16 @@ public class SessionDelegatorBaseImpl implements SessionImplementor {
}
@Override
public void lock(String entityName, Object object, LockOptions lockOptions) {
delegate.lock( entityName, object, lockOptions );
}
@Override
public void lock(Object object, LockOptions lockOptions) {
delegate.lock( object, lockOptions );
}
@Override @Deprecated
public LockRequest buildLockRequest(LockOptions lockOptions) {
return delegate.buildLockRequest( lockOptions );
}

View File

@ -281,6 +281,17 @@ public class SessionLazyDelegator implements Session {
}
@Override
public void lock(Object object, LockOptions lockOptions) {
this.lazySession.get().lock( object, lockOptions );
}
@Override
public void lock(String entityName, Object object, LockOptions lockOptions) {
this.lazySession.get().lock( entityName, object, lockOptions );
}
@Override
@Deprecated
public LockRequest buildLockRequest(LockOptions lockOptions) {
return this.lazySession.get().buildLockRequest( lockOptions );
}

View File

@ -674,12 +674,22 @@ public class SessionImpl
// lock() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public void lock(Object object, LockOptions lockOptions) {
fireLock( new LockEvent( object, lockOptions, this ) );
}
@Override
public void lock(String entityName, Object object, LockOptions lockOptions) {
fireLock( new LockEvent( entityName, object, lockOptions, this ) );
}
@Override
public void lock(String entityName, Object object, LockMode lockMode) throws HibernateException {
fireLock( new LockEvent( entityName, object, lockMode, this ) );
}
@Override
@Override @Deprecated
public LockRequest buildLockRequest(LockOptions lockOptions) {
return new LockRequestImpl( lockOptions );
}
@ -2109,6 +2119,7 @@ public class SessionImpl
}
}
@Deprecated
private class LockRequestImpl implements LockRequest {
private final LockOptions lockOptions;