From eb59e81bb945ad3a3e010c19440f66376c5bd08a Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Wed, 30 Nov 2011 12:19:24 -0600 Subject: [PATCH] HHH-6865 - PessimisticLockException should be thrown when pessimistic read and write locking strategies fail --- .../hibernate/OptimisticLockException.java | 29 ++----- .../hibernate/PessimisticLockException.java | 29 +------ .../internal/EntityVerifyVersionProcess.java | 1 + .../dialect/lock/LockingStrategy.java | 8 +- .../lock/LockingStrategyException.java | 49 ++++++++++++ .../lock/OptimisticEntityLockException.java | 39 ++++++++++ ...timisticForceIncrementLockingStrategy.java | 13 +--- .../lock/OptimisticLockingStrategy.java | 18 ++--- .../lock/PessimisticEntityLockException.java | 37 +++++++++ ...simisticForceIncrementLockingStrategy.java | 14 +--- .../PessimisticReadSelectLockingStrategy.java | 76 +++++++++---------- .../PessimisticReadUpdateLockingStrategy.java | 72 +++++++++--------- ...PessimisticWriteSelectLockingStrategy.java | 76 +++++++++---------- ...PessimisticWriteUpdateLockingStrategy.java | 74 +++++++++--------- .../dialect/lock/SelectLockingStrategy.java | 3 +- .../dialect/lock/UpdateLockingStrategy.java | 13 ++-- .../ejb/AbstractEntityManagerImpl.java | 31 +++++--- 17 files changed, 332 insertions(+), 250 deletions(-) create mode 100644 hibernate-core/src/main/java/org/hibernate/dialect/lock/LockingStrategyException.java create mode 100644 hibernate-core/src/main/java/org/hibernate/dialect/lock/OptimisticEntityLockException.java create mode 100644 hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticEntityLockException.java diff --git a/hibernate-core/src/main/java/org/hibernate/OptimisticLockException.java b/hibernate-core/src/main/java/org/hibernate/OptimisticLockException.java index 1184860db4..87ad02b1ef 100644 --- a/hibernate-core/src/main/java/org/hibernate/OptimisticLockException.java +++ b/hibernate-core/src/main/java/org/hibernate/OptimisticLockException.java @@ -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; - } - - } \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/PessimisticLockException.java b/hibernate-core/src/main/java/org/hibernate/PessimisticLockException.java index bbb43ff106..c89660ad5d 100644 --- a/hibernate-core/src/main/java/org/hibernate/PessimisticLockException.java +++ b/hibernate-core/src/main/java/org/hibernate/PessimisticLockException.java @@ -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 ); } - } \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/action/internal/EntityVerifyVersionProcess.java b/hibernate-core/src/main/java/org/hibernate/action/internal/EntityVerifyVersionProcess.java index 5e31574175..85b99a30da 100644 --- a/hibernate-core/src/main/java/org/hibernate/action/internal/EntityVerifyVersionProcess.java +++ b/hibernate-core/src/main/java/org/hibernate/action/internal/EntityVerifyVersionProcess.java @@ -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" diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/LockingStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/LockingStrategy.java index d1080ebfce..6976ec4bd5 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/lock/LockingStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/LockingStrategy.java @@ -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 JDBC 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; } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/LockingStrategyException.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/LockingStrategyException.java new file mode 100644 index 0000000000..05a346d702 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/LockingStrategyException.java @@ -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; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/OptimisticEntityLockException.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/OptimisticEntityLockException.java new file mode 100644 index 0000000000..a5a2552688 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/OptimisticEntityLockException.java @@ -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 ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/OptimisticForceIncrementLockingStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/OptimisticForceIncrementLockingStrategy.java index 5bc7c17615..506b262254 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/lock/OptimisticForceIncrementLockingStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/OptimisticForceIncrementLockingStrategy.java @@ -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() + "]" ); } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/OptimisticLockingStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/OptimisticLockingStrategy.java index e6e37f276a..3730c226e8 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/lock/OptimisticLockingStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/OptimisticLockingStrategy.java @@ -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; *

* 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; diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticEntityLockException.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticEntityLockException.java new file mode 100644 index 0000000000..5929143ef7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticEntityLockException.java @@ -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 ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticForceIncrementLockingStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticForceIncrementLockingStrategy.java index 8d8c015d61..c74fde749f 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticForceIncrementLockingStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticForceIncrementLockingStrategy.java @@ -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() + "]" ); } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadSelectLockingStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadSelectLockingStrategy.java index 085e518082..2545d2e2f5 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadSelectLockingStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadSelectLockingStrategy.java @@ -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 ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadUpdateLockingStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadUpdateLockingStrategy.java index 46db8185a7..60a96df95b 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadUpdateLockingStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadUpdateLockingStrategy.java @@ -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 ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteSelectLockingStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteSelectLockingStrategy.java index 147c5e7eda..613e4f423c 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteSelectLockingStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteSelectLockingStrategy.java @@ -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 ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteUpdateLockingStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteUpdateLockingStrategy.java index 2b1a542843..c9838fa832 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteUpdateLockingStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteUpdateLockingStrategy.java @@ -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 ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/SelectLockingStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/SelectLockingStrategy.java index f5d110559f..8bf732f049 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/lock/SelectLockingStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/SelectLockingStrategy.java @@ -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 { /** diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/UpdateLockingStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/UpdateLockingStrategy.java index 816e4ddec1..b38b96df46 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/lock/UpdateLockingStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/UpdateLockingStrategy.java @@ -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; *

* 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, diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java index a418c48fc7..ed2e0b6966 100755 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java @@ -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 {