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.SharedSessionContractImplementor;
import org.hibernate.persister.entity.Lockable;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.sql.SimpleSelect;
public class SelectLockingStrategy extends AbstractSelectLockingStrategy {
public SelectLockingStrategy(Lockable lockable, LockMode lockMode) {
super( lockable, lockMode );
}
@Override
public void lock(
Serializable id,
Object version,
Object object,
int timeout,
SharedSessionContractImplementor session) throws StaleObjectStateException, JDBCException {
final String sql = determineSql( timeout );
final SessionFactoryImplementor factory = session.getFactory();
try {
final PreparedStatement st = session.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.getJdbcCoordinator().getResultSetReturn().extract( st );
try {
if ( !rs.next() ) {
if ( factory.getStatistics().isStatisticsEnabled() ) {
factory.getStatistics().optimisticFailure( getLockable().getEntityName() );
}
throw new StaleObjectStateException( getLockable().getEntityName(), id );
}
}
finally {
session.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release( rs, st );
}
}
finally {
session.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
}
}
catch ( SQLException sqle ) {
throw session.getJdbcServices().getSqlExceptionHelper().convert(
sqle,
"could not lock: " + MessageHelper.infoString( getLockable(), 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.getDialect() )
.setLockOptions( lockOptions )
.setTableName( getLockable().getRootTableName() )
.addColumn( getLockable().getRootTableIdentifierColumnNames()[0] )
.addCondition( getLockable().getRootTableIdentifierColumnNames(), "=?" );
if ( getLockable().isVersioned() ) {
select.addCondition( getLockable().getVersionColumnName(), "=?" );
}
if ( factory.getSessionFactoryOptions().isCommentsEnabled() ) {
select.setComment( getLockMode() + " lock " + getLockable().getEntityName() );
}
return select.toStatementString();
}
}