clean up locking strategies
- remove duplicated code - handle UPGRADE_NOWAIT and UPGRADE_SKIPLOCKED as flavors of PessimisticWriteSelectLockingStrategy - improve Javadoc Signed-off-by: Gavin King <gavin@hibernate.org>
This commit is contained in:
parent
1b67ebee60
commit
54d34a445c
|
@ -808,14 +808,28 @@ public interface Session extends SharedSessionContract, EntityManager {
|
|||
|
||||
/**
|
||||
* Obtain the specified lock level on the given managed instance associated
|
||||
* with this session. This may be used to:
|
||||
* with this session. This operation 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}).
|
||||
* <li>perform a version check on an entity read from the second-level cache
|
||||
* by requesting {@link LockMode#READ},
|
||||
* <li>schedule a version check at transaction commit by requesting
|
||||
* {@link LockMode#OPTIMISTIC},
|
||||
* <li>schedule a version increment at transaction commit by requesting
|
||||
* {@link LockMode#OPTIMISTIC_FORCE_INCREMENT}
|
||||
* <li>upgrade to a pessimistic lock with {@link LockMode#PESSIMISTIC_READ}
|
||||
* or {@link LockMode#PESSIMISTIC_WRITE}, or
|
||||
* <li>immediately increment the version of the given instance by requesting
|
||||
* {@link LockMode#PESSIMISTIC_FORCE_INCREMENT}.
|
||||
* </ul>
|
||||
* <p>
|
||||
* If the requested lock mode is already held on the given entity, this
|
||||
* operation has no effect.
|
||||
* <p>
|
||||
* This operation cascades to associated instances if the association is
|
||||
* mapped with {@link org.hibernate.annotations.CascadeType#LOCK}.
|
||||
* <p>
|
||||
* The modes {@link LockMode#WRITE} and {@link LockMode#UPGRADE_SKIPLOCKED}
|
||||
* are not legal arguments to {@code lock()}.
|
||||
*
|
||||
* @param object a persistent instance
|
||||
* @param lockMode the lock level
|
||||
|
|
|
@ -34,7 +34,7 @@ public class EntityVerifyVersionProcess implements BeforeTransactionCompletionPr
|
|||
@Override
|
||||
public void doBeforeTransactionCompletion(SessionImplementor session) {
|
||||
final EntityEntry entry = session.getPersistenceContext().getEntry( object );
|
||||
// Don't check version for an entity that is not in the PersistenceContext;
|
||||
// Don't check version for an entity that is not in the PersistenceContext
|
||||
if ( entry != null ) {
|
||||
final Object latestVersion = entry.getPersister().getCurrentVersion( entry.getId(), session );
|
||||
if ( !entry.getVersion().equals( latestVersion ) ) {
|
||||
|
|
|
@ -2018,16 +2018,21 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
|
|||
switch ( lockMode ) {
|
||||
case PESSIMISTIC_FORCE_INCREMENT:
|
||||
return new PessimisticForceIncrementLockingStrategy( lockable, lockMode );
|
||||
case UPGRADE_NOWAIT:
|
||||
case UPGRADE_SKIPLOCKED:
|
||||
case PESSIMISTIC_WRITE:
|
||||
return new PessimisticWriteSelectLockingStrategy( lockable, lockMode );
|
||||
case PESSIMISTIC_READ:
|
||||
return new PessimisticReadSelectLockingStrategy( lockable, lockMode );
|
||||
case OPTIMISTIC:
|
||||
return new OptimisticLockingStrategy( lockable, lockMode );
|
||||
case OPTIMISTIC_FORCE_INCREMENT:
|
||||
return new OptimisticForceIncrementLockingStrategy( lockable, lockMode );
|
||||
default:
|
||||
case OPTIMISTIC:
|
||||
return new OptimisticLockingStrategy( lockable, lockMode );
|
||||
case READ:
|
||||
return new SelectLockingStrategy( lockable, lockMode );
|
||||
default:
|
||||
// WRITE, NONE are not allowed here
|
||||
throw new IllegalArgumentException( "Unsupported lock mode" );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,13 +6,29 @@
|
|||
*/
|
||||
package org.hibernate.dialect.lock;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.JDBCException;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.StaleObjectStateException;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.event.spi.EventSource;
|
||||
import org.hibernate.persister.entity.Lockable;
|
||||
import org.hibernate.sql.SimpleSelect;
|
||||
import org.hibernate.stat.spi.StatisticsImplementor;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import static org.hibernate.pretty.MessageHelper.infoString;
|
||||
|
||||
/**
|
||||
* Base {@link LockingStrategy} implementation to support implementations
|
||||
* based on issuing {@code SQL} {@code SELECT} statements
|
||||
* based on issuing SQL {@code SELECT} statements. For non-read locks,
|
||||
* this is achieved via the dialect's native {@code SELECT ... FOR UPDATE}
|
||||
* syntax.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
@ -35,19 +51,87 @@ public abstract class AbstractSelectLockingStrategy implements LockingStrategy {
|
|||
return lockMode;
|
||||
}
|
||||
|
||||
protected abstract String generateLockString(int lockTimeout);
|
||||
protected String generateLockString(int lockTimeout) {
|
||||
final SessionFactoryImplementor factory = lockable.getFactory();
|
||||
final LockOptions lockOptions = new LockOptions( lockMode );
|
||||
lockOptions.setTimeOut( lockTimeout );
|
||||
final SimpleSelect select =
|
||||
new SimpleSelect( factory )
|
||||
.setLockOptions( lockOptions )
|
||||
.setTableName( lockable.getRootTableName() )
|
||||
.addColumn( lockable.getRootTableIdentifierColumnNames()[0] )
|
||||
.addRestriction( lockable.getRootTableIdentifierColumnNames() );
|
||||
if ( lockable.isVersioned() ) {
|
||||
select.addRestriction( lockable.getVersionColumnName() );
|
||||
}
|
||||
if ( factory.getSessionFactoryOptions().isCommentsEnabled() ) {
|
||||
select.setComment( lockMode + " lock " + lockable.getEntityName() );
|
||||
}
|
||||
return select.toStatementString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lock(Object id, Object version, Object object, int timeout, EventSource session)
|
||||
throws StaleObjectStateException, JDBCException {
|
||||
final String sql = determineSql( timeout );
|
||||
final SessionFactoryImplementor factory = session.getFactory();
|
||||
final Lockable lockable = getLockable();
|
||||
try {
|
||||
final JdbcCoordinator jdbcCoordinator = session.getJdbcCoordinator();
|
||||
final PreparedStatement st = jdbcCoordinator.getStatementPreparer().prepareStatement( sql );
|
||||
try {
|
||||
lockable.getIdentifierType().nullSafeSet( st, id, 1, session );
|
||||
if ( lockable.isVersioned() ) {
|
||||
lockable.getVersionType().nullSafeSet(
|
||||
st,
|
||||
version,
|
||||
lockable.getIdentifierType().getColumnSpan( factory ) + 1,
|
||||
session
|
||||
);
|
||||
}
|
||||
|
||||
final ResultSet rs = jdbcCoordinator.getResultSetReturn().extract( st, sql );
|
||||
try {
|
||||
if ( !rs.next() ) {
|
||||
final StatisticsImplementor statistics = factory.getStatistics();
|
||||
if ( statistics.isStatisticsEnabled() ) {
|
||||
statistics.optimisticFailure( lockable.getEntityName() );
|
||||
}
|
||||
throw new StaleObjectStateException( lockable.getEntityName(), id );
|
||||
}
|
||||
}
|
||||
finally {
|
||||
jdbcCoordinator.getLogicalConnection().getResourceRegistry().release( rs, st );
|
||||
}
|
||||
}
|
||||
finally {
|
||||
jdbcCoordinator.getLogicalConnection().getResourceRegistry().release( st );
|
||||
jdbcCoordinator.afterStatementExecution();
|
||||
}
|
||||
}
|
||||
catch ( SQLException sqle ) {
|
||||
throw convertException( object, jdbcException( id, session, sqle, sql ) );
|
||||
}
|
||||
}
|
||||
|
||||
private JDBCException jdbcException(Object id, EventSource session, SQLException sqle, String sql) {
|
||||
return session.getJdbcServices().getSqlExceptionHelper()
|
||||
.convert( sqle, "could not lock: " + infoString( lockable, id, session.getFactory() ), sql );
|
||||
}
|
||||
|
||||
protected HibernateException convertException(Object entity, JDBCException ex) {
|
||||
return ex;
|
||||
}
|
||||
|
||||
protected String determineSql(int timeout) {
|
||||
if ( timeout == LockOptions.WAIT_FOREVER) {
|
||||
switch (timeout) {
|
||||
case LockOptions.WAIT_FOREVER:
|
||||
return waitForeverSql;
|
||||
}
|
||||
else if ( timeout == LockOptions.NO_WAIT) {
|
||||
case LockOptions.NO_WAIT:
|
||||
return getNoWaitSql();
|
||||
}
|
||||
else if ( timeout == LockOptions.SKIP_LOCKED) {
|
||||
case LockOptions.SKIP_LOCKED:
|
||||
return getSkipLockedSql();
|
||||
}
|
||||
else {
|
||||
default:
|
||||
return generateLockString( timeout );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ public class OptimisticForceIncrementLockingStrategy implements LockingStrategy
|
|||
if ( !lockable.isVersioned() ) {
|
||||
throw new HibernateException( "[" + lockMode + "] not supported for non-versioned entities [" + lockable.getEntityName() + "]" );
|
||||
}
|
||||
final EntityEntry entry = session.getPersistenceContextInternal().getEntry( object );
|
||||
// final EntityEntry entry = session.getPersistenceContextInternal().getEntry( object );
|
||||
// Register the EntityIncrementVersionProcess action to run just prior to transaction commit.
|
||||
session.getActionQueue().registerProcess( new EntityIncrementVersionProcess( object ) );
|
||||
}
|
||||
|
|
|
@ -6,32 +6,18 @@
|
|||
*/
|
||||
package org.hibernate.dialect.lock;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.JDBCException;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.StaleObjectStateException;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.event.spi.EventSource;
|
||||
import org.hibernate.persister.entity.Lockable;
|
||||
import org.hibernate.pretty.MessageHelper;
|
||||
import org.hibernate.sql.SimpleSelect;
|
||||
import org.hibernate.stat.spi.StatisticsImplementor;
|
||||
|
||||
/**
|
||||
* A pessimistic locking strategy where a lock is obtained via a
|
||||
* select statements.
|
||||
* A pessimistic locking strategy where {@link LockMode#PESSIMISTIC_READ}
|
||||
* is obtained via a select statement.
|
||||
* <p>
|
||||
* For non-read locks, this is achieved through the dialect's native
|
||||
* {@code SELECT ... FOR UPDATE} syntax.
|
||||
* <p>
|
||||
* This strategy is valid for {@link LockMode#PESSIMISTIC_READ}.
|
||||
* <p>
|
||||
* This class is a clone of {@link SelectLockingStrategy}.
|
||||
* Differs from {@link SelectLockingStrategy} in throwing
|
||||
* {@link PessimisticEntityLockException}.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Scott Marlow
|
||||
|
@ -53,68 +39,7 @@ public class PessimisticReadSelectLockingStrategy extends AbstractSelectLockingS
|
|||
}
|
||||
|
||||
@Override
|
||||
public void lock(Object id, Object version, Object object, int timeout, EventSource session) {
|
||||
final String sql = determineSql( timeout );
|
||||
final SessionFactoryImplementor factory = session.getFactory();
|
||||
try {
|
||||
final Lockable lockable = getLockable();
|
||||
try {
|
||||
final JdbcCoordinator jdbcCoordinator = session.getJdbcCoordinator();
|
||||
final PreparedStatement st = jdbcCoordinator.getStatementPreparer().prepareStatement( sql );
|
||||
try {
|
||||
lockable.getIdentifierType().nullSafeSet( st, id, 1, session );
|
||||
if ( lockable.isVersioned() ) {
|
||||
lockable.getVersionType().nullSafeSet(
|
||||
st,
|
||||
version,
|
||||
lockable.getIdentifierType().getColumnSpan( factory ) + 1,
|
||||
session
|
||||
);
|
||||
}
|
||||
|
||||
final ResultSet rs = jdbcCoordinator.getResultSetReturn().extract( st, sql );
|
||||
if ( !rs.next() ) {
|
||||
final StatisticsImplementor statistics = factory.getStatistics();
|
||||
if ( statistics.isStatisticsEnabled() ) {
|
||||
statistics.optimisticFailure( lockable.getEntityName() );
|
||||
}
|
||||
throw new StaleObjectStateException( lockable.getEntityName(), id );
|
||||
}
|
||||
}
|
||||
finally {
|
||||
jdbcCoordinator.getLogicalConnection().getResourceRegistry().release( st );
|
||||
jdbcCoordinator.afterStatementExecution();
|
||||
}
|
||||
|
||||
}
|
||||
catch ( SQLException e ) {
|
||||
throw session.getJdbcServices().getSqlExceptionHelper().convert(
|
||||
e,
|
||||
"could not lock: " + MessageHelper.infoString( lockable, id, session.getFactory() ),
|
||||
sql
|
||||
);
|
||||
}
|
||||
}
|
||||
catch (JDBCException e) {
|
||||
throw new PessimisticEntityLockException( object, "could not obtain pessimistic lock", e );
|
||||
}
|
||||
}
|
||||
|
||||
protected String generateLockString(int lockTimeout) {
|
||||
final SessionFactoryImplementor factory = getLockable().getFactory();
|
||||
final LockOptions lockOptions = new LockOptions( getLockMode() );
|
||||
lockOptions.setTimeOut( lockTimeout );
|
||||
final SimpleSelect select = new SimpleSelect( factory )
|
||||
.setLockOptions( lockOptions )
|
||||
.setTableName( getLockable().getRootTableName() )
|
||||
.addColumn( getLockable().getRootTableIdentifierColumnNames()[0] )
|
||||
.addRestriction( getLockable().getRootTableIdentifierColumnNames() );
|
||||
if ( getLockable().isVersioned() ) {
|
||||
select.addRestriction( getLockable().getVersionColumnName() );
|
||||
}
|
||||
if ( factory.getSessionFactoryOptions().isCommentsEnabled() ) {
|
||||
select.setComment( getLockMode() + " lock " + getLockable().getEntityName() );
|
||||
}
|
||||
return select.toStatementString();
|
||||
protected HibernateException convertException(Object entity, JDBCException ex) {
|
||||
return new PessimisticEntityLockException( entity, "could not obtain pessimistic lock", ex );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,32 +6,18 @@
|
|||
*/
|
||||
package org.hibernate.dialect.lock;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.JDBCException;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.StaleObjectStateException;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.event.spi.EventSource;
|
||||
import org.hibernate.persister.entity.Lockable;
|
||||
import org.hibernate.pretty.MessageHelper;
|
||||
import org.hibernate.sql.SimpleSelect;
|
||||
import org.hibernate.stat.spi.StatisticsImplementor;
|
||||
|
||||
/**
|
||||
* A pessimistic locking strategy where a lock is obtained via a
|
||||
* select statement.
|
||||
* A pessimistic locking strategy where {@link LockMode#PESSIMISTIC_WRITE}
|
||||
* lock is obtained via a select statement.
|
||||
* <p>
|
||||
* For non-read locks, this is achieved through the dialect's native
|
||||
* {@code SELECT ... FOR UPDATE} syntax.
|
||||
* <p>
|
||||
* This strategy is valid for {@link LockMode#PESSIMISTIC_WRITE}.
|
||||
* <p>
|
||||
* This class is a clone of {@link SelectLockingStrategy}.
|
||||
* Differs from {@link SelectLockingStrategy} in throwing
|
||||
* {@link PessimisticEntityLockException}.
|
||||
*
|
||||
* @see org.hibernate.dialect.Dialect#getForUpdateString(LockMode)
|
||||
* @see org.hibernate.dialect.Dialect#appendLockHint(LockOptions, String)
|
||||
|
@ -52,72 +38,7 @@ public class PessimisticWriteSelectLockingStrategy extends AbstractSelectLocking
|
|||
}
|
||||
|
||||
@Override
|
||||
public void lock(Object id, Object version, Object object, int timeout, EventSource session) {
|
||||
final String sql = determineSql( timeout );
|
||||
final SessionFactoryImplementor factory = session.getFactory();
|
||||
try {
|
||||
final Lockable lockable = getLockable();
|
||||
try {
|
||||
final JdbcCoordinator jdbcCoordinator = session.getJdbcCoordinator();
|
||||
final PreparedStatement st = jdbcCoordinator.getStatementPreparer().prepareStatement( sql );
|
||||
try {
|
||||
lockable.getIdentifierType().nullSafeSet( st, id, 1, session );
|
||||
if ( lockable.isVersioned() ) {
|
||||
lockable.getVersionType().nullSafeSet(
|
||||
st,
|
||||
version,
|
||||
lockable.getIdentifierType().getColumnSpan( factory ) + 1,
|
||||
session
|
||||
);
|
||||
}
|
||||
|
||||
final ResultSet rs = jdbcCoordinator.getResultSetReturn().extract( st, sql );
|
||||
try {
|
||||
if ( !rs.next() ) {
|
||||
final StatisticsImplementor statistics = factory.getStatistics();
|
||||
if ( statistics.isStatisticsEnabled() ) {
|
||||
statistics.optimisticFailure( lockable.getEntityName() );
|
||||
}
|
||||
throw new StaleObjectStateException( lockable.getEntityName(), id );
|
||||
}
|
||||
}
|
||||
finally {
|
||||
jdbcCoordinator.getLogicalConnection().getResourceRegistry().release( rs, st );
|
||||
}
|
||||
}
|
||||
finally {
|
||||
jdbcCoordinator.getLogicalConnection().getResourceRegistry().release( st );
|
||||
jdbcCoordinator.afterStatementExecution();
|
||||
}
|
||||
}
|
||||
catch ( SQLException e ) {
|
||||
throw session.getJdbcServices().getSqlExceptionHelper().convert(
|
||||
e,
|
||||
"could not lock: " + MessageHelper.infoString( lockable, id, session.getFactory() ),
|
||||
sql
|
||||
);
|
||||
}
|
||||
}
|
||||
catch (JDBCException e) {
|
||||
throw new PessimisticEntityLockException( object, "could not obtain pessimistic lock", e );
|
||||
}
|
||||
}
|
||||
|
||||
protected String generateLockString(int lockTimeout) {
|
||||
final SessionFactoryImplementor factory = getLockable().getFactory();
|
||||
final LockOptions lockOptions = new LockOptions( getLockMode() );
|
||||
lockOptions.setTimeOut( lockTimeout );
|
||||
final SimpleSelect select = new SimpleSelect( factory )
|
||||
.setLockOptions( lockOptions )
|
||||
.setTableName( getLockable().getRootTableName() )
|
||||
.addColumn( getLockable().getRootTableIdentifierColumnNames()[0] )
|
||||
.addRestriction( getLockable().getRootTableIdentifierColumnNames() );
|
||||
if ( getLockable().isVersioned() ) {
|
||||
select.addRestriction( getLockable().getVersionColumnName() );
|
||||
}
|
||||
if ( factory.getSessionFactoryOptions().isCommentsEnabled() ) {
|
||||
select.setComment( getLockMode() + " lock " + getLockable().getEntityName() );
|
||||
}
|
||||
return select.toStatementString();
|
||||
protected HibernateException convertException(Object entity, JDBCException ex) {
|
||||
return new PessimisticEntityLockException( entity, "could not obtain pessimistic lock", ex );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,27 +6,19 @@
|
|||
*/
|
||||
package org.hibernate.dialect.lock;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.JDBCException;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.StaleObjectStateException;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.event.spi.EventSource;
|
||||
import org.hibernate.persister.entity.Lockable;
|
||||
import org.hibernate.pretty.MessageHelper;
|
||||
import org.hibernate.sql.SimpleSelect;
|
||||
import org.hibernate.stat.spi.StatisticsImplementor;
|
||||
|
||||
/**
|
||||
* A locking strategy where a lock is obtained via a select statement.
|
||||
/**
|
||||
* A locking strategy where an optimistic lock is obtained via a select
|
||||
* statement.
|
||||
* <p>
|
||||
* For non-read locks, this is achieved through the dialect's native
|
||||
* {@code SELECT ... FOR UPDATE} syntax.
|
||||
* Differs from {@link PessimisticWriteSelectLockingStrategy} and
|
||||
* {@link PessimisticReadSelectLockingStrategy} in throwing
|
||||
* {@link OptimisticEntityLockException}.
|
||||
*
|
||||
* @see org.hibernate.dialect.Dialect#getForUpdateString(LockMode)
|
||||
* @see org.hibernate.dialect.Dialect#appendLockHint(LockOptions, String)
|
||||
|
@ -46,73 +38,7 @@ public class SelectLockingStrategy extends AbstractSelectLockingStrategy {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void lock(
|
||||
Object id,
|
||||
Object version,
|
||||
Object object,
|
||||
int timeout,
|
||||
EventSource session) throws StaleObjectStateException, JDBCException {
|
||||
final String sql = determineSql( timeout );
|
||||
final SessionFactoryImplementor factory = session.getFactory();
|
||||
final Lockable lockable = getLockable();
|
||||
try {
|
||||
final JdbcCoordinator jdbcCoordinator = session.getJdbcCoordinator();
|
||||
final PreparedStatement st = jdbcCoordinator.getStatementPreparer().prepareStatement( sql );
|
||||
try {
|
||||
lockable.getIdentifierType().nullSafeSet( st, id, 1, session );
|
||||
if ( lockable.isVersioned() ) {
|
||||
lockable.getVersionType().nullSafeSet(
|
||||
st,
|
||||
version,
|
||||
lockable.getIdentifierType().getColumnSpan( factory ) + 1,
|
||||
session
|
||||
);
|
||||
}
|
||||
|
||||
final ResultSet rs = jdbcCoordinator.getResultSetReturn().extract( st, sql );
|
||||
try {
|
||||
if ( !rs.next() ) {
|
||||
final StatisticsImplementor statistics = factory.getStatistics();
|
||||
if ( statistics.isStatisticsEnabled() ) {
|
||||
statistics.optimisticFailure( lockable.getEntityName() );
|
||||
}
|
||||
throw new StaleObjectStateException( lockable.getEntityName(), id );
|
||||
}
|
||||
}
|
||||
finally {
|
||||
jdbcCoordinator.getLogicalConnection().getResourceRegistry().release( rs, st );
|
||||
}
|
||||
}
|
||||
finally {
|
||||
jdbcCoordinator.getLogicalConnection().getResourceRegistry().release( st );
|
||||
jdbcCoordinator.afterStatementExecution();
|
||||
}
|
||||
|
||||
}
|
||||
catch ( SQLException sqle ) {
|
||||
throw session.getJdbcServices().getSqlExceptionHelper().convert(
|
||||
sqle,
|
||||
"could not lock: " + MessageHelper.infoString( lockable, id, session.getFactory() ),
|
||||
sql
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected String generateLockString(int timeout) {
|
||||
final SessionFactoryImplementor factory = getLockable().getFactory();
|
||||
final LockOptions lockOptions = new LockOptions( getLockMode() );
|
||||
lockOptions.setTimeOut( timeout );
|
||||
final SimpleSelect select = new SimpleSelect( factory )
|
||||
.setLockOptions( lockOptions )
|
||||
.setTableName( getLockable().getRootTableName() )
|
||||
.addColumn( getLockable().getRootTableIdentifierColumnNames()[0] )
|
||||
.addRestriction( getLockable().getRootTableIdentifierColumnNames() );
|
||||
if ( getLockable().isVersioned() ) {
|
||||
select.addRestriction( getLockable().getVersionColumnName() );
|
||||
}
|
||||
if ( factory.getSessionFactoryOptions().isCommentsEnabled() ) {
|
||||
select.setComment( getLockMode() + " lock " + getLockable().getEntityName() );
|
||||
}
|
||||
return select.toStatementString();
|
||||
protected HibernateException convertException(Object entity, JDBCException ex) {
|
||||
return new OptimisticEntityLockException( entity, "could not obtain optimistic lock", ex );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,8 +51,7 @@ public class LoaderHelper {
|
|||
public static void upgradeLock(Object object, EntityEntry entry, LockOptions lockOptions, EventSource session) {
|
||||
final LockMode requestedLockMode = lockOptions.getLockMode();
|
||||
if ( requestedLockMode.greaterThan( entry.getLockMode() ) ) {
|
||||
// The user requested a "greater" (i.e. more restrictive) form of
|
||||
// pessimistic lock
|
||||
// Request is for a more restrictive lock than the lock already held
|
||||
|
||||
if ( entry.getStatus().isDeletedOrGone()) {
|
||||
throw new ObjectDeletedException(
|
||||
|
|
Loading…
Reference in New Issue