HHH-6865 - PessimisticLockException should be thrown when pessimistic read and write locking strategies fail

This commit is contained in:
Steve Ebersole 2011-11-30 12:19:24 -06:00
parent 3577cbde08
commit eb59e81bb9
17 changed files with 332 additions and 250 deletions

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2009-2011, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,33 +20,20 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate;
import org.hibernate.dialect.lock.OptimisticEntityLockException;
/**
*
* Throw when an optimistic locking conflict occurs.
*
* @author Scott Marlow
*
* @deprecated Use {@link org.hibernate.dialect.lock.OptimisticEntityLockException} instead
*/
public class OptimisticLockException extends HibernateException {
Object entity;
public OptimisticLockException(String s) {
super(s);
public class OptimisticLockException extends OptimisticEntityLockException {
public OptimisticLockException(Object entity, String message) {
super( entity, message );
}
public OptimisticLockException(String s, Object entity) {
super(s);
this.entity = entity;
}
public Object getEntity() {
return entity;
}
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2009-2011, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,39 +20,18 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate;
import java.sql.SQLException;
/**
*
* Thrown when a pessimistic locking conflict occurs.
*
* @author Scott Marlow
*/
public class PessimisticLockException extends JDBCException {
Object entity;
public PessimisticLockException(String s, JDBCException je, Object entity) {
super(s, je.getSQLException());
this.entity = entity;
}
public PessimisticLockException(String s, SQLException se, Object entity) {
super(s, se);
this.entity = entity;
}
public PessimisticLockException(String s, SQLException se, String sql) {
super(s, se, sql);
this.entity = null;
}
public Object getEntity() {
return entity;
super( s, se, sql );
}
}

View File

@ -52,6 +52,7 @@ public class EntityVerifyVersionProcess implements BeforeTransactionCompletionPr
Object latestVersion = persister.getCurrentVersion( entry.getId(), session );
if ( !entry.getVersion().equals( latestVersion ) ) {
throw new OptimisticLockException(
object,
"Newer version [" + latestVersion +
"] of entity [" + MessageHelper.infoString( entry.getEntityName(), entry.getId() ) +
"] found in database"

View File

@ -51,10 +51,10 @@ public interface LockingStrategy {
* @param object The object logically being locked (currently not used)
* @param timeout timeout in milliseconds, 0 = no wait, -1 = wait indefinitely
* @param session The session from which the lock request originated
* @throws StaleObjectStateException Indicates an optimistic lock failure
* as part of acquiring the requested database lock.
* @throws JDBCException Indicates errors from the <tt>JDBC</tt> driver.
* @throws StaleObjectStateException Indicates an inability to locate the database row as part of acquiring
* the requested lock.
* @throws LockingStrategyException Indicates a failure in the lock attempt
*/
public void lock(Serializable id, Object version, Object object, int timeout, SessionImplementor session)
throws StaleObjectStateException, JDBCException;
throws StaleObjectStateException, LockingStrategyException;
}

View File

@ -0,0 +1,49 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.lock;
import org.hibernate.HibernateException;
/**
* Represents an error trying to apply a {@link LockingStrategy} to an entity
*
* @author Steve Ebersole
*/
public abstract class LockingStrategyException extends HibernateException {
private final Object entity;
public LockingStrategyException(Object entity, String message) {
super( message );
this.entity = entity;
}
public LockingStrategyException(Object entity, String message, Throwable root) {
super( message, root );
this.entity = entity;
}
public Object getEntity() {
return entity;
}
}

View File

@ -0,0 +1,39 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.lock;
/**
* Represents an error trying to apply an optimistic {@link LockingStrategy} to an entity
*
* @author Steve Ebersole
*/
public class OptimisticEntityLockException extends LockingStrategyException {
public OptimisticEntityLockException(Object entity, String message) {
super( entity, message );
}
public OptimisticEntityLockException(Object entity, String message, Throwable root) {
super( entity, message, root );
}
}

View File

@ -22,12 +22,11 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.lock;
import java.io.Serializable;
import org.hibernate.HibernateException;
import org.hibernate.JDBCException;
import org.hibernate.LockMode;
import org.hibernate.StaleObjectStateException;
import org.hibernate.action.internal.EntityIncrementVersionProcess;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.SessionImplementor;
@ -61,14 +60,8 @@ public class OptimisticForceIncrementLockingStrategy implements LockingStrategy
}
}
/**
* @see LockingStrategy#lock
*/
public void lock(
Serializable id,
Object version,
Object object,
int timeout, SessionImplementor session) throws StaleObjectStateException, JDBCException {
@Override
public void lock(Serializable id, Object version, Object object, int timeout, SessionImplementor session) {
if ( !lockable.isVersioned() ) {
throw new HibernateException( "[" + lockMode + "] not supported for non-versioned entities [" + lockable.getEntityName() + "]" );
}

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.lock;
import java.io.Serializable;
import org.hibernate.HibernateException;
@ -40,9 +41,8 @@ import org.hibernate.persister.entity.Lockable;
* <p/>
* This strategy is valid for LockMode.OPTIMISTIC
*
* @since 3.5
*
* @author Scott Marlow
* @since 3.5
*/
public class OptimisticLockingStrategy implements LockingStrategy {
@ -53,7 +53,7 @@ public class OptimisticLockingStrategy implements LockingStrategy {
* Construct locking strategy.
*
* @param lockable The metadata for the entity to be locked.
* @param lockMode Indictates the type of lock to be acquired.
* @param lockMode Indicates the type of lock to be acquired.
*/
public OptimisticLockingStrategy(Lockable lockable, LockMode lockMode) {
this.lockable = lockable;
@ -63,16 +63,10 @@ public class OptimisticLockingStrategy implements LockingStrategy {
}
}
/**
* @see org.hibernate.dialect.lock.LockingStrategy#lock
*/
public void lock(
Serializable id,
Object version,
Object object,
int timeout, SessionImplementor session) throws StaleObjectStateException, JDBCException {
@Override
public void lock(Serializable id, Object version, Object object, int timeout, SessionImplementor session) {
if ( !lockable.isVersioned() ) {
throw new OptimisticLockException( "[" + lockMode + "] not supported for non-versioned entities [" + lockable.getEntityName() + "]" );
throw new OptimisticLockException( object, "[" + lockMode + "] not supported for non-versioned entities [" + lockable.getEntityName() + "]" );
}
EntityEntry entry = session.getPersistenceContext().getEntry(object);
EventSource source = (EventSource)session;

View File

@ -0,0 +1,37 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.lock;
import org.hibernate.JDBCException;
/**
* Represents an error trying to apply a pessimistic {@link LockingStrategy} to an entity
*
* @author Steve Ebersole
*/
public class PessimisticEntityLockException extends LockingStrategyException {
public PessimisticEntityLockException(Object entity, String message, JDBCException root) {
super( entity, message, root );
}
}

View File

@ -22,12 +22,11 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.lock;
import java.io.Serializable;
import org.hibernate.HibernateException;
import org.hibernate.JDBCException;
import org.hibernate.LockMode;
import org.hibernate.StaleObjectStateException;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.persister.entity.EntityPersister;
@ -60,15 +59,8 @@ public class PessimisticForceIncrementLockingStrategy implements LockingStrategy
}
}
/**
* {@inheritDoc}
*/
public void lock(
Serializable id,
Object version,
Object object,
int timeout,
SessionImplementor session) throws StaleObjectStateException, JDBCException {
@Override
public void lock(Serializable id, Object version, Object object, int timeout, SessionImplementor session) {
if ( !lockable.isVersioned() ) {
throw new HibernateException( "[" + lockMode + "] not supported for non-versioned entities [" + lockable.getEntityName() + "]" );
}

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.lock;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@ -50,8 +51,10 @@ import org.hibernate.sql.SimpleSelect;
*
* @author Steve Ebersole
* @author Scott Marlow
*
* @see org.hibernate.dialect.Dialect#getForUpdateString(org.hibernate.LockMode)
* @see org.hibernate.dialect.Dialect#appendLockHint(org.hibernate.LockMode, String)
*
* @since 3.5
*/
public class PessimisticReadSelectLockingStrategy extends AbstractSelectLockingStrategy {
@ -65,56 +68,53 @@ public class PessimisticReadSelectLockingStrategy extends AbstractSelectLockingS
super( lockable, lockMode );
}
/**
* @see org.hibernate.dialect.lock.LockingStrategy#lock
*/
public void lock(
Serializable id,
Object version,
Object object,
int timeout,
SessionImplementor session) throws StaleObjectStateException, JDBCException {
@Override
public void lock(Serializable id, Object version, Object object, int timeout, SessionImplementor session) {
final String sql = determineSql( timeout );
SessionFactoryImplementor factory = session.getFactory();
try {
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
);
}
ResultSet rs = st.executeQuery();
PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
if ( !rs.next() ) {
if ( factory.getStatistics().isStatisticsEnabled() ) {
factory.getStatisticsImplementor()
.optimisticFailure( getLockable().getEntityName() );
getLockable().getIdentifierType().nullSafeSet( st, id, 1, session );
if ( getLockable().isVersioned() ) {
getLockable().getVersionType().nullSafeSet(
st,
version,
getLockable().getIdentifierType().getColumnSpan( factory ) + 1,
session
);
}
ResultSet rs = st.executeQuery();
try {
if ( !rs.next() ) {
if ( factory.getStatistics().isStatisticsEnabled() ) {
factory.getStatisticsImplementor()
.optimisticFailure( getLockable().getEntityName() );
}
throw new StaleObjectStateException( getLockable().getEntityName(), id );
}
throw new StaleObjectStateException( getLockable().getEntityName(), id );
}
finally {
rs.close();
}
}
finally {
rs.close();
st.close();
}
}
finally {
st.close();
}
}
catch ( SQLException e ) {
throw session.getFactory().getSQLExceptionHelper().convert(
e,
"could not lock: " + MessageHelper.infoString( getLockable(), id, session.getFactory() ),
sql
);
}
}
catch ( SQLException sqle ) {
JDBCException e = session.getFactory().getSQLExceptionHelper().convert(
sqle,
"could not lock: " + MessageHelper.infoString( getLockable(), id, session.getFactory() ),
sql
);
throw new PessimisticLockException( "could not obtain pessimistic lock", e, object );
catch (JDBCException e) {
throw new PessimisticEntityLockException( object, "could not obtain pessimistic lock", e );
}
}

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.lock;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.SQLException;
@ -47,15 +48,16 @@ import org.hibernate.sql.Update;
*
* This class is a clone of UpdateLockingStrategy.
*
* @since 3.5
*
* @author Steve Ebersole
* @author Scott Marlow
* @since 3.5
*/
public class PessimisticReadUpdateLockingStrategy implements LockingStrategy {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class,
PessimisticReadUpdateLockingStrategy.class.getName());
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
PessimisticReadUpdateLockingStrategy.class.getName()
);
private final Lockable lockable;
private final LockMode lockMode;
@ -65,7 +67,7 @@ public class PessimisticReadUpdateLockingStrategy implements LockingStrategy {
* Construct a locking strategy based on SQL UPDATE statements.
*
* @param lockable The metadata for the entity to be locked.
* @param lockMode Indictates the type of lock to be acquired. Note that
* @param lockMode Indicates the type of lock to be acquired. Note that
* read-locks are not valid for this strategy.
*/
public PessimisticReadUpdateLockingStrategy(Lockable lockable, LockMode lockMode) {
@ -83,50 +85,48 @@ public class PessimisticReadUpdateLockingStrategy implements LockingStrategy {
}
}
/**
* @see org.hibernate.dialect.lock.LockingStrategy#lock
*/
public void lock(
Serializable id,
Object version,
Object object,
int timeout, SessionImplementor session) throws StaleObjectStateException, JDBCException {
@Override
public void lock(Serializable id, Object version, Object object, int timeout, SessionImplementor session) {
if ( !lockable.isVersioned() ) {
throw new HibernateException( "write locks via update not supported for non-versioned entities [" + lockable.getEntityName() + "]" );
}
SessionFactoryImplementor factory = session.getFactory();
try {
PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
lockable.getVersionType().nullSafeSet( st, version, 1, session );
int offset = 2;
PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
lockable.getVersionType().nullSafeSet( st, version, 1, session );
int offset = 2;
lockable.getIdentifierType().nullSafeSet( st, id, offset, session );
offset += lockable.getIdentifierType().getColumnSpan( factory );
lockable.getIdentifierType().nullSafeSet( st, id, offset, session );
offset += lockable.getIdentifierType().getColumnSpan( factory );
if ( lockable.isVersioned() ) {
lockable.getVersionType().nullSafeSet( st, version, offset, session );
}
int affected = st.executeUpdate();
if ( affected < 0 ) { // todo: should this instead check for exactly one row modified?
factory.getStatisticsImplementor().optimisticFailure( lockable.getEntityName() );
throw new StaleObjectStateException( lockable.getEntityName(), id );
}
if ( lockable.isVersioned() ) {
lockable.getVersionType().nullSafeSet( st, version, offset, session );
}
int affected = st.executeUpdate();
if ( affected < 0 ) { // todo: should this instead check for exactly one row modified?
factory.getStatisticsImplementor().optimisticFailure( lockable.getEntityName() );
throw new StaleObjectStateException( lockable.getEntityName(), id );
finally {
st.close();
}
}
finally {
st.close();
}
}
catch ( SQLException sqle ) {
JDBCException e = session.getFactory().getSQLExceptionHelper().convert(
sqle,
"could not lock: " + MessageHelper.infoString( lockable, id, session.getFactory() ),
sql
catch ( SQLException e ) {
throw session.getFactory().getSQLExceptionHelper().convert(
e,
"could not lock: " + MessageHelper.infoString( lockable, id, session.getFactory() ),
sql
);
throw new PessimisticLockException("could not obtain pessimistic lock", e, object);
}
}
catch (JDBCException e) {
throw new PessimisticEntityLockException( object, "could not obtain pessimistic lock", e );
}
}

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.lock;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@ -48,10 +49,11 @@ import org.hibernate.sql.SimpleSelect;
*
* This class is a clone of SelectLockingStrategy.
*
* @author Steve Ebersole
* @author Scott Marlow
* @see org.hibernate.dialect.Dialect#getForUpdateString(org.hibernate.LockMode)
* @see org.hibernate.dialect.Dialect#appendLockHint(org.hibernate.LockMode, String)
*
* @author Steve Ebersole
* @author Scott Marlow
* @since 3.5
*/
public class PessimisticWriteSelectLockingStrategy extends AbstractSelectLockingStrategy {
@ -65,56 +67,52 @@ public class PessimisticWriteSelectLockingStrategy extends AbstractSelectLocking
super( lockable, lockMode );
}
/**
* @see LockingStrategy#lock
*/
public void lock(
Serializable id,
Object version,
Object object,
int timeout,
SessionImplementor session) throws StaleObjectStateException, JDBCException {
@Override
public void lock(Serializable id, Object version, Object object, int timeout, SessionImplementor session) {
final String sql = determineSql( timeout );
SessionFactoryImplementor factory = session.getFactory();
try {
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
);
}
ResultSet rs = st.executeQuery();
PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
if ( !rs.next() ) {
if ( factory.getStatistics().isStatisticsEnabled() ) {
factory.getStatisticsImplementor()
.optimisticFailure( getLockable().getEntityName() );
getLockable().getIdentifierType().nullSafeSet( st, id, 1, session );
if ( getLockable().isVersioned() ) {
getLockable().getVersionType().nullSafeSet(
st,
version,
getLockable().getIdentifierType().getColumnSpan( factory ) + 1,
session
);
}
ResultSet rs = st.executeQuery();
try {
if ( !rs.next() ) {
if ( factory.getStatistics().isStatisticsEnabled() ) {
factory.getStatisticsImplementor()
.optimisticFailure( getLockable().getEntityName() );
}
throw new StaleObjectStateException( getLockable().getEntityName(), id );
}
throw new StaleObjectStateException( getLockable().getEntityName(), id );
}
finally {
rs.close();
}
}
finally {
rs.close();
st.close();
}
}
finally {
st.close();
catch ( SQLException e ) {
throw session.getFactory().getSQLExceptionHelper().convert(
e,
"could not lock: " + MessageHelper.infoString( getLockable(), id, session.getFactory() ),
sql
);
}
}
catch ( SQLException sqle ) {
JDBCException e = session.getFactory().getSQLExceptionHelper().convert(
sqle,
"could not lock: " + MessageHelper.infoString( getLockable(), id, session.getFactory() ),
sql
);
throw new PessimisticLockException( "could not obtain pessimistic lock", e, object );
catch (JDBCException e) {
throw new PessimisticEntityLockException( object, "could not obtain pessimistic lock", e );
}
}

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.lock;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.SQLException;
@ -47,15 +48,16 @@ import org.hibernate.sql.Update;
*
* This class is a clone of UpdateLockingStrategy.
*
* @since 3.5
*
* @author Steve Ebersole
* @author Scott Marlow
* @since 3.5
*/
public class PessimisticWriteUpdateLockingStrategy implements LockingStrategy {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class,
PessimisticWriteUpdateLockingStrategy.class.getName());
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
PessimisticWriteUpdateLockingStrategy.class.getName()
);
private final Lockable lockable;
private final LockMode lockMode;
@ -65,8 +67,7 @@ public class PessimisticWriteUpdateLockingStrategy implements LockingStrategy {
* Construct a locking strategy based on SQL UPDATE statements.
*
* @param lockable The metadata for the entity to be locked.
* @param lockMode Indictates the type of lock to be acquired. Note that
* read-locks are not valid for this strategy.
* @param lockMode Indicates the type of lock to be acquired. Note that read-locks are not valid for this strategy.
*/
public PessimisticWriteUpdateLockingStrategy(Lockable lockable, LockMode lockMode) {
this.lockable = lockable;
@ -83,50 +84,47 @@ public class PessimisticWriteUpdateLockingStrategy implements LockingStrategy {
}
}
/**
* @see LockingStrategy#lock
*/
public void lock(
Serializable id,
Object version,
Object object,
int timeout, SessionImplementor session) throws StaleObjectStateException, JDBCException {
@Override
public void lock(Serializable id, Object version, Object object, int timeout, SessionImplementor session) {
if ( !lockable.isVersioned() ) {
throw new HibernateException( "write locks via update not supported for non-versioned entities [" + lockable.getEntityName() + "]" );
}
SessionFactoryImplementor factory = session.getFactory();
try {
PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
lockable.getVersionType().nullSafeSet( st, version, 1, session );
int offset = 2;
PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
lockable.getVersionType().nullSafeSet( st, version, 1, session );
int offset = 2;
lockable.getIdentifierType().nullSafeSet( st, id, offset, session );
offset += lockable.getIdentifierType().getColumnSpan( factory );
lockable.getIdentifierType().nullSafeSet( st, id, offset, session );
offset += lockable.getIdentifierType().getColumnSpan( factory );
if ( lockable.isVersioned() ) {
lockable.getVersionType().nullSafeSet( st, version, offset, session );
}
int affected = st.executeUpdate();
if ( affected < 0 ) { // todo: should this instead check for exactly one row modified?
factory.getStatisticsImplementor().optimisticFailure( lockable.getEntityName() );
throw new StaleObjectStateException( lockable.getEntityName(), id );
}
if ( lockable.isVersioned() ) {
lockable.getVersionType().nullSafeSet( st, version, offset, session );
}
int affected = st.executeUpdate();
if ( affected < 0 ) { // todo: should this instead check for exactly one row modified?
factory.getStatisticsImplementor().optimisticFailure( lockable.getEntityName() );
throw new StaleObjectStateException( lockable.getEntityName(), id );
finally {
st.close();
}
}
finally {
st.close();
}
}
catch ( SQLException sqle ) {
JDBCException e = session.getFactory().getSQLExceptionHelper().convert(
sqle,
"could not lock: " + MessageHelper.infoString( lockable, id, session.getFactory() ),
sql
catch ( SQLException e ) {
throw session.getFactory().getSQLExceptionHelper().convert(
e,
"could not lock: " + MessageHelper.infoString( lockable, id, session.getFactory() ),
sql
);
throw new PessimisticLockException("could not obtain pessimistic lock", e, object);
}
}
catch (JDBCException e) {
throw new PessimisticEntityLockException( object, "could not obtain pessimistic lock", e );
}
}

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.lock;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@ -45,9 +46,9 @@ import org.hibernate.sql.SimpleSelect;
*
* @see org.hibernate.dialect.Dialect#getForUpdateString(org.hibernate.LockMode)
* @see org.hibernate.dialect.Dialect#appendLockHint(org.hibernate.LockMode, String)
* @since 3.2
*
* @author Steve Ebersole
* @since 3.2
*/
public class SelectLockingStrategy extends AbstractSelectLockingStrategy {
/**

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.lock;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.SQLException;
@ -44,13 +45,15 @@ import org.hibernate.sql.Update;
* <p/>
* This strategy is not valid for read style locks.
*
* @since 3.2
*
* @author Steve Ebersole
* @since 3.2
*/
public class UpdateLockingStrategy implements LockingStrategy {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, UpdateLockingStrategy.class.getName());
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
UpdateLockingStrategy.class.getName()
);
private final Lockable lockable;
private final LockMode lockMode;
@ -78,9 +81,7 @@ public class UpdateLockingStrategy implements LockingStrategy {
}
}
/**
* @see LockingStrategy#lock
*/
@Override
public void lock(
Serializable id,
Object version,

View File

@ -83,6 +83,9 @@ import org.hibernate.TransientObjectException;
import org.hibernate.TypeMismatchException;
import org.hibernate.UnresolvableObjectException;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.lock.LockingStrategyException;
import org.hibernate.dialect.lock.OptimisticEntityLockException;
import org.hibernate.dialect.lock.PessimisticEntityLockException;
import org.hibernate.ejb.criteria.CriteriaQueryCompiler;
import org.hibernate.ejb.criteria.ValueHandlerFactory;
import org.hibernate.ejb.criteria.expression.CompoundSelectionImpl;
@ -1301,7 +1304,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
handlePersistenceException( converted );
return converted;
}
else if ( e instanceof org.hibernate.OptimisticLockException ) {
else if ( e instanceof LockingStrategyException ) {
PersistenceException converted = wrapLockException( e, lockOptions );
handlePersistenceException( converted );
return converted;
@ -1397,19 +1400,29 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
}
public PersistenceException wrapLockException(HibernateException e, LockOptions lockOptions) {
PersistenceException pe;
if ( e instanceof org.hibernate.OptimisticLockException ) {
org.hibernate.OptimisticLockException ole = ( org.hibernate.OptimisticLockException ) e;
pe = new OptimisticLockException( ole.getMessage(), ole, ole.getEntity() );
final PersistenceException pe;
if ( e instanceof OptimisticEntityLockException ) {
final OptimisticEntityLockException lockException = (OptimisticEntityLockException) e;
pe = new OptimisticLockException( lockException.getMessage(), lockException, lockException.getEntity() );
}
else if ( e instanceof org.hibernate.PessimisticLockException ) {
org.hibernate.PessimisticLockException ple = ( org.hibernate.PessimisticLockException ) e;
else if ( e instanceof PessimisticEntityLockException ) {
PessimisticEntityLockException lockException = (PessimisticEntityLockException) e;
if ( lockOptions != null && lockOptions.getTimeOut() > -1 ) {
// assume lock timeout occurred if a timeout or NO WAIT was specified
pe = new LockTimeoutException( ple.getMessage(), ple, ple.getEntity() );
pe = new LockTimeoutException( lockException.getMessage(), lockException, lockException.getEntity() );
}
else {
pe = new PessimisticLockException( ple.getMessage(), ple, ple.getEntity() );
pe = new PessimisticLockException( lockException.getMessage(), lockException, lockException.getEntity() );
}
}
else if ( e instanceof org.hibernate.PessimisticLockException ) {
org.hibernate.PessimisticLockException jdbcLockException = ( org.hibernate.PessimisticLockException ) e;
if ( lockOptions != null && lockOptions.getTimeOut() > -1 ) {
// assume lock timeout occurred if a timeout or NO WAIT was specified
pe = new LockTimeoutException( jdbcLockException.getMessage(), jdbcLockException, null );
}
else {
pe = new PessimisticLockException( jdbcLockException.getMessage(), jdbcLockException, null );
}
}
else {