package org.hibernate.dialect.lock;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.hibernate.JDBCException;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.StaleObjectStateException;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.persister.entity.Lockable;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.sql.SimpleSelect;
public class PessimisticReadSelectLockingStrategy extends AbstractSelectLockingStrategy {
public PessimisticReadSelectLockingStrategy(Lockable lockable, LockMode lockMode) {
super( lockable, lockMode );
}
@Override
public void lock(Serializable id, Object version, Object object, int timeout, SessionImplementor session) {
final String sql = determineSql( timeout );
final SessionFactoryImplementor factory = session.getFactory();
try {
try {
final PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
getLockable().getIdentifierType().nullSafeSet( st, id, 1, session );
if ( getLockable().isVersioned() ) {
getLockable().getVersionType().nullSafeSet(
st,
version,
getLockable().getIdentifierType().getColumnSpan( factory ) + 1,
session
);
}
final ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( st );
try {
if ( !rs.next() ) {
if ( factory.getStatistics().isStatisticsEnabled() ) {
factory.getStatisticsImplementor()
.optimisticFailure( getLockable().getEntityName() );
}
throw new StaleObjectStateException( getLockable().getEntityName(), id );
}
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( rs, st );
}
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
}
}
catch ( SQLException e ) {
throw session.getFactory().getSQLExceptionHelper().convert(
e,
"could not lock: " + MessageHelper.infoString( getLockable(), 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.getDialect() )
.setLockOptions( lockOptions )
.setTableName( getLockable().getRootTableName() )
.addColumn( getLockable().getRootTableIdentifierColumnNames()[0] )
.addCondition( getLockable().getRootTableIdentifierColumnNames(), "=?" );
if ( getLockable().isVersioned() ) {
select.addCondition( getLockable().getVersionColumnName(), "=?" );
}
if ( factory.getSettings().isCommentsEnabled() ) {
select.setComment( getLockMode() + " lock " + getLockable().getEntityName() );
}
return select.toStatementString();
}
}