[hibernate-commits] Hibernate SVN: r19095 - in core/trunk: core/src/main/java/org/hibernate/dialect/lock and 7 other directories.
hibernate-commits at lists.jboss.org
hibernate-commits at lists.jboss.org
Wed Mar 24 10:37:59 EDT 2010
Author: steve.ebersole at jboss.com
Date: 2010-03-24 10:37:56 -0400 (Wed, 24 Mar 2010)
New Revision: 19095
Added:
core/trunk/core/src/main/java/org/hibernate/dialect/lock/AbstractSelectLockingStrategy.java
Modified:
core/trunk/core/src/main/java/org/hibernate/dialect/Dialect.java
core/trunk/core/src/main/java/org/hibernate/dialect/HSQLDialect.java
core/trunk/core/src/main/java/org/hibernate/dialect/lock/LockingStrategy.java
core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticReadSelectLockingStrategy.java
core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteSelectLockingStrategy.java
core/trunk/core/src/main/java/org/hibernate/dialect/lock/SelectLockingStrategy.java
core/trunk/core/src/main/java/org/hibernate/engine/QueryParameters.java
core/trunk/core/src/main/java/org/hibernate/event/def/DefaultLoadEventListener.java
core/trunk/core/src/main/java/org/hibernate/loader/Loader.java
core/trunk/core/src/main/java/org/hibernate/loader/entity/AbstractEntityLoader.java
core/trunk/core/src/main/java/org/hibernate/loader/entity/BatchingEntityLoader.java
core/trunk/core/src/main/java/org/hibernate/loader/entity/EntityLoader.java
core/trunk/core/src/main/java/org/hibernate/loader/entity/UniqueEntityLoader.java
core/trunk/core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
core/trunk/core/src/main/java/org/hibernate/persister/entity/NamedQueryLoader.java
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java
core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/lock/LockTest.java
Log:
HHH-5009 - Support NOWAIT for "SELECT ... FOR UPDATE" with JPA interfaces
Modified: core/trunk/core/src/main/java/org/hibernate/dialect/Dialect.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/Dialect.java 2010-03-24 12:18:25 UTC (rev 19094)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/Dialect.java 2010-03-24 14:37:56 UTC (rev 19095)
@@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
- * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * Copyright (c) 2010, 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,7 +20,6 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
- *
*/
package org.hibernate.dialect;
@@ -943,6 +942,34 @@
// lock acquisition support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
+ * Informational metadata about whether this dialect is known to support
+ * specifying timeouts for requested lock acquisitions.
+ *
+ * @return True is this dialect supports specifying lock timeouts.
+ */
+ public boolean supportsLockTimeouts() {
+ return true;
+
+ }
+
+ /**
+ * If this dialect supports specifying lock timeouts, are those timeouts
+ * rendered into the <tt>SQL</tt> string as parameters. The implication
+ * is that Hibernate will need to bind the timeout value as a parameter
+ * in the {@link java.sql.PreparedStatement}. If true, the param position
+ * is always handled as the last parameter; if the dialect specifies the
+ * lock timeout elsewhere in the <tt>SQL</tt> statement then the timeout
+ * value should be directly rendered into the statement and this method
+ * should return false.
+ *
+ * @return True if the lock timeout is rendered into the <tt>SQL</tt>
+ * string as a parameter; false otherwise.
+ */
+ public boolean isLockTimeoutParameterized() {
+ return false;
+ }
+
+ /**
* Get a strategy instance which knows how to acquire a database-level lock
* of the specified mode for this dialect.
*
Modified: core/trunk/core/src/main/java/org/hibernate/dialect/HSQLDialect.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/HSQLDialect.java 2010-03-24 12:18:25 UTC (rev 19094)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/HSQLDialect.java 2010-03-24 14:37:56 UTC (rev 19095)
@@ -173,6 +173,10 @@
return "null";
}
+ public boolean supportsLockTimeouts() {
+ return false;
+ }
+
public String getForUpdateString() {
return "";
}
Added: core/trunk/core/src/main/java/org/hibernate/dialect/lock/AbstractSelectLockingStrategy.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/lock/AbstractSelectLockingStrategy.java (rev 0)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/lock/AbstractSelectLockingStrategy.java 2010-03-24 14:37:56 UTC (rev 19095)
@@ -0,0 +1,73 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, 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.LockMode;
+import org.hibernate.LockOptions;
+import org.hibernate.persister.entity.Lockable;
+
+/**
+ * Base {@link LockingStrategy} implementation to support implementations
+ * based on issuing <tt>SQL</tt> <tt>SELECT</tt> statements
+ *
+ * @author Steve Ebersole
+ */
+public abstract class AbstractSelectLockingStrategy implements LockingStrategy {
+ private final Lockable lockable;
+ private final LockMode lockMode;
+ private final String waitForeverSql;
+
+ protected AbstractSelectLockingStrategy(Lockable lockable, LockMode lockMode) {
+ this.lockable = lockable;
+ this.lockMode = lockMode;
+ this.waitForeverSql = generateLockString( LockOptions.WAIT_FOREVER );
+ }
+
+ protected Lockable getLockable() {
+ return lockable;
+ }
+
+ protected LockMode getLockMode() {
+ return lockMode;
+ }
+
+ protected abstract String generateLockString(int lockTimeout);
+
+ protected String determineSql(int timeout) {
+ return timeout == LockOptions.WAIT_FOREVER
+ ? waitForeverSql
+ : timeout == LockOptions.NO_WAIT
+ ? getNoWaitSql()
+ : generateLockString( timeout );
+ }
+
+ private String noWaitSql;
+
+ public String getNoWaitSql() {
+ if ( noWaitSql == null ) {
+ noWaitSql = generateLockString( LockOptions.NO_WAIT );
+ }
+ return noWaitSql;
+ }
+}
Modified: core/trunk/core/src/main/java/org/hibernate/dialect/lock/LockingStrategy.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/lock/LockingStrategy.java 2010-03-24 12:18:25 UTC (rev 19094)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/lock/LockingStrategy.java 2010-03-24 14:37:56 UTC (rev 19095)
@@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
- * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * Copyright (c) 2010, 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,7 +20,6 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
- *
*/
package org.hibernate.dialect.lock;
@@ -33,7 +32,7 @@
/**
* A strategy abstraction for how locks are obtained in the underlying database.
* <p/>
- * All locking provided implemenations assume the underlying database supports
+ * All locking provided implementations assume the underlying database supports
* (and that the connection is in) at least read-committed transaction isolation.
* The most glaring exclusion to this is HSQLDB which only offers support for
* READ_UNCOMMITTED isolation.
@@ -53,9 +52,9 @@
* @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 optimisitic lock failure
+ * @throws StaleObjectStateException Indicates an optimistic lock failure
* as part of acquiring the requested database lock.
- * @throws JDBCException
+ * @throws JDBCException Indicates errors from the <tt>JDBC</tt> driver.
*/
public void lock(Serializable id, Object version, Object object, int timeout, SessionImplementor session)
throws StaleObjectStateException, JDBCException;
Modified: core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticReadSelectLockingStrategy.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticReadSelectLockingStrategy.java 2010-03-24 12:18:25 UTC (rev 19094)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticReadSelectLockingStrategy.java 2010-03-24 14:37:56 UTC (rev 19095)
@@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
- * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
+ * Copyright (c) 2010, 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,7 +20,6 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
- *
*/
package org.hibernate.dialect.lock;
@@ -51,57 +50,43 @@
*
* 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)
* @since 3.5
- *
- * @author Steve Ebersole
- * @author Scott Marlow
*/
-public class PessimisticReadSelectLockingStrategy implements LockingStrategy {
-
- private final Lockable lockable;
- private final LockMode lockMode;
- private final String sql;
-
+public class PessimisticReadSelectLockingStrategy extends AbstractSelectLockingStrategy {
/**
* Construct a locking strategy based on SQL SELECT statements.
*
* @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 PessimisticReadSelectLockingStrategy(Lockable lockable, LockMode lockMode) {
- this.lockable = lockable;
- this.lockMode = lockMode;
- this.sql = generateLockString(LockOptions.WAIT_FOREVER);
+ 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 {
- String sql = this.sql;
- if ( timeout == LockOptions.NO_WAIT ) {
- sql = generateLockString( LockOptions.NO_WAIT );
- }
- else if ( timeout > 0) {
- sql = generateLockString( timeout );
- }
-
+ Serializable id,
+ Object version,
+ Object object,
+ int timeout,
+ SessionImplementor session) throws StaleObjectStateException, JDBCException {
+ final String sql = determineSql( timeout );
SessionFactoryImplementor factory = session.getFactory();
try {
PreparedStatement st = session.getBatcher().prepareSelectStatement( sql );
try {
- lockable.getIdentifierType().nullSafeSet( st, id, 1, session );
- if ( lockable.isVersioned() ) {
- lockable.getVersionType().nullSafeSet(
+ getLockable().getIdentifierType().nullSafeSet( st, id, 1, session );
+ if ( getLockable().isVersioned() ) {
+ getLockable().getVersionType().nullSafeSet(
st,
version,
- lockable.getIdentifierType().getColumnSpan( factory ) + 1,
+ getLockable().getIdentifierType().getColumnSpan( factory ) + 1,
session
);
}
@@ -111,9 +96,9 @@
if ( !rs.next() ) {
if ( factory.getStatistics().isStatisticsEnabled() ) {
factory.getStatisticsImplementor()
- .optimisticFailure( lockable.getEntityName() );
+ .optimisticFailure( getLockable().getEntityName() );
}
- throw new StaleObjectStateException( lockable.getEntityName(), id );
+ throw new StaleObjectStateException( getLockable().getEntityName(), id );
}
}
finally {
@@ -129,31 +114,27 @@
JDBCException e = JDBCExceptionHelper.convert(
session.getFactory().getSQLExceptionConverter(),
sqle,
- "could not lock: " + MessageHelper.infoString( lockable, id, session.getFactory() ),
+ "could not lock: " + MessageHelper.infoString( getLockable(), id, session.getFactory() ),
sql
- );
- throw new PessimisticLockException("could not obtain pessimistic lock", e, object);
+ );
+ throw new PessimisticLockException( "could not obtain pessimistic lock", e, object );
}
}
- protected LockMode getLockMode() {
- return lockMode;
- }
-
protected String generateLockString(int lockTimeout) {
- SessionFactoryImplementor factory = lockable.getFactory();
- LockOptions lockOptions = new LockOptions(this.lockMode);
+ SessionFactoryImplementor factory = getLockable().getFactory();
+ LockOptions lockOptions = new LockOptions( getLockMode() );
lockOptions.setTimeOut( lockTimeout );
SimpleSelect select = new SimpleSelect( factory.getDialect() )
.setLockOptions( lockOptions )
- .setTableName( lockable.getRootTableName() )
- .addColumn( lockable.getRootTableIdentifierColumnNames()[0] )
- .addCondition( lockable.getRootTableIdentifierColumnNames(), "=?" );
- if ( lockable.isVersioned() ) {
- select.addCondition( lockable.getVersionColumnName(), "=?" );
+ .setTableName( getLockable().getRootTableName() )
+ .addColumn( getLockable().getRootTableIdentifierColumnNames()[0] )
+ .addCondition( getLockable().getRootTableIdentifierColumnNames(), "=?" );
+ if ( getLockable().isVersioned() ) {
+ select.addCondition( getLockable().getVersionColumnName(), "=?" );
}
if ( factory.getSettings().isCommentsEnabled() ) {
- select.setComment( lockMode + " lock " + lockable.getEntityName() );
+ select.setComment( getLockMode() + " lock " + getLockable().getEntityName() );
}
return select.toStatementString();
}
Modified: core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteSelectLockingStrategy.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteSelectLockingStrategy.java 2010-03-24 12:18:25 UTC (rev 19094)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteSelectLockingStrategy.java 2010-03-24 14:37:56 UTC (rev 19095)
@@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
- * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
+ * Copyright (c) 2010, 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,7 +20,6 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
- *
*/
package org.hibernate.dialect.lock;
@@ -46,62 +45,48 @@
* <p/>
* For non-read locks, this is achieved through the Dialect's specific
* SELECT ... FOR UPDATE syntax.
- *
+ *
* This strategy is valid for LockMode.PESSIMISTIC_WRITE
*
* 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)
* @since 3.5
- *
- * @author Steve Ebersole
- * @author Scott Marlow
*/
-public class PessimisticWriteSelectLockingStrategy implements LockingStrategy {
-
- private final Lockable lockable;
- private final LockMode lockMode;
- private final String sql;
-
+public class PessimisticWriteSelectLockingStrategy extends AbstractSelectLockingStrategy {
/**
* Construct a locking strategy based on SQL SELECT statements.
*
* @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 PessimisticWriteSelectLockingStrategy(Lockable lockable, LockMode lockMode) {
- this.lockable = lockable;
- this.lockMode = lockMode;
- this.sql = generateLockString(LockOptions.WAIT_FOREVER);
+ super( lockable, lockMode );
}
- /**
+ /**
* @see LockingStrategy#lock
*/
public void lock(
- Serializable id,
- Object version,
- Object object,
- int timeout, SessionImplementor session) throws StaleObjectStateException, JDBCException {
- String sql = this.sql;
- if ( timeout == LockOptions.NO_WAIT ) {
- sql = generateLockString( LockOptions.NO_WAIT );
- }
- else if ( timeout > 0) {
- sql = generateLockString( timeout );
- }
-
+ Serializable id,
+ Object version,
+ Object object,
+ int timeout,
+ SessionImplementor session) throws StaleObjectStateException, JDBCException {
+ final String sql = determineSql( timeout );
SessionFactoryImplementor factory = session.getFactory();
try {
PreparedStatement st = session.getBatcher().prepareSelectStatement( sql );
try {
- lockable.getIdentifierType().nullSafeSet( st, id, 1, session );
- if ( lockable.isVersioned() ) {
- lockable.getVersionType().nullSafeSet(
+ getLockable().getIdentifierType().nullSafeSet( st, id, 1, session );
+ if ( getLockable().isVersioned() ) {
+ getLockable().getVersionType().nullSafeSet(
st,
version,
- lockable.getIdentifierType().getColumnSpan( factory ) + 1,
+ getLockable().getIdentifierType().getColumnSpan( factory ) + 1,
session
);
}
@@ -111,9 +96,9 @@
if ( !rs.next() ) {
if ( factory.getStatistics().isStatisticsEnabled() ) {
factory.getStatisticsImplementor()
- .optimisticFailure( lockable.getEntityName() );
+ .optimisticFailure( getLockable().getEntityName() );
}
- throw new StaleObjectStateException( lockable.getEntityName(), id );
+ throw new StaleObjectStateException( getLockable().getEntityName(), id );
}
}
finally {
@@ -129,31 +114,27 @@
JDBCException e = JDBCExceptionHelper.convert(
session.getFactory().getSQLExceptionConverter(),
sqle,
- "could not lock: " + MessageHelper.infoString( lockable, id, session.getFactory() ),
+ "could not lock: " + MessageHelper.infoString( getLockable(), id, session.getFactory() ),
sql
- );
- throw new PessimisticLockException("could not obtain pessimistic lock", e, object);
+ );
+ throw new PessimisticLockException( "could not obtain pessimistic lock", e, object );
}
}
- protected LockMode getLockMode() {
- return lockMode;
- }
-
protected String generateLockString(int lockTimeout) {
- SessionFactoryImplementor factory = lockable.getFactory();
- LockOptions lockOptions = new LockOptions(this.lockMode);
+ SessionFactoryImplementor factory = getLockable().getFactory();
+ LockOptions lockOptions = new LockOptions( getLockMode() );
lockOptions.setTimeOut( lockTimeout );
SimpleSelect select = new SimpleSelect( factory.getDialect() )
.setLockOptions( lockOptions )
- .setTableName( lockable.getRootTableName() )
- .addColumn( lockable.getRootTableIdentifierColumnNames()[0] )
- .addCondition( lockable.getRootTableIdentifierColumnNames(), "=?" );
- if ( lockable.isVersioned() ) {
- select.addCondition( lockable.getVersionColumnName(), "=?" );
+ .setTableName( getLockable().getRootTableName() )
+ .addColumn( getLockable().getRootTableIdentifierColumnNames()[0] )
+ .addCondition( getLockable().getRootTableIdentifierColumnNames(), "=?" );
+ if ( getLockable().isVersioned() ) {
+ select.addCondition( getLockable().getVersionColumnName(), "=?" );
}
if ( factory.getSettings().isCommentsEnabled() ) {
- select.setComment( lockMode + " lock " + lockable.getEntityName() );
+ select.setComment( getLockMode() + " lock " + getLockable().getEntityName() );
}
return select.toStatementString();
}
Modified: core/trunk/core/src/main/java/org/hibernate/dialect/lock/SelectLockingStrategy.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/lock/SelectLockingStrategy.java 2010-03-24 12:18:25 UTC (rev 19094)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/lock/SelectLockingStrategy.java 2010-03-24 14:37:56 UTC (rev 19095)
@@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
- * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * Copyright (c) 2010, 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,10 +20,10 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
- *
*/
package org.hibernate.dialect.lock;
+import org.hibernate.LockOptions;
import org.hibernate.persister.entity.Lockable;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.engine.SessionFactoryImplementor;
@@ -51,12 +51,7 @@
*
* @author Steve Ebersole
*/
-public class SelectLockingStrategy implements LockingStrategy {
-
- private final Lockable lockable;
- private final LockMode lockMode;
- private final String sql;
-
+public class SelectLockingStrategy extends AbstractSelectLockingStrategy {
/**
* Construct a locking strategy based on SQL SELECT statements.
*
@@ -64,9 +59,7 @@
* @param lockMode Indictates the type of lock to be acquired.
*/
public SelectLockingStrategy(Lockable lockable, LockMode lockMode) {
- this.lockable = lockable;
- this.lockMode = lockMode;
- this.sql = generateLockString();
+ super( lockable, lockMode );
}
/**
@@ -78,17 +71,17 @@
Object object,
int timeout,
SessionImplementor session) throws StaleObjectStateException, JDBCException {
-
+ final String sql = determineSql( timeout );
SessionFactoryImplementor factory = session.getFactory();
try {
PreparedStatement st = session.getBatcher().prepareSelectStatement( sql );
try {
- lockable.getIdentifierType().nullSafeSet( st, id, 1, session );
- if ( lockable.isVersioned() ) {
- lockable.getVersionType().nullSafeSet(
+ getLockable().getIdentifierType().nullSafeSet( st, id, 1, session );
+ if ( getLockable().isVersioned() ) {
+ getLockable().getVersionType().nullSafeSet(
st,
version,
- lockable.getIdentifierType().getColumnSpan( factory ) + 1,
+ getLockable().getIdentifierType().getColumnSpan( factory ) + 1,
session
);
}
@@ -98,9 +91,9 @@
if ( !rs.next() ) {
if ( factory.getStatistics().isStatisticsEnabled() ) {
factory.getStatisticsImplementor()
- .optimisticFailure( lockable.getEntityName() );
+ .optimisticFailure( getLockable().getEntityName() );
}
- throw new StaleObjectStateException( lockable.getEntityName(), id );
+ throw new StaleObjectStateException( getLockable().getEntityName(), id );
}
}
finally {
@@ -116,28 +109,26 @@
throw JDBCExceptionHelper.convert(
session.getFactory().getSQLExceptionConverter(),
sqle,
- "could not lock: " + MessageHelper.infoString( lockable, id, session.getFactory() ),
+ "could not lock: " + MessageHelper.infoString( getLockable(), id, session.getFactory() ),
sql
);
}
}
- protected LockMode getLockMode() {
- return lockMode;
- }
-
- protected String generateLockString() {
- SessionFactoryImplementor factory = lockable.getFactory();
+ protected String generateLockString(int timeout) {
+ SessionFactoryImplementor factory = getLockable().getFactory();
+ LockOptions lockOptions = new LockOptions( getLockMode() );
+ lockOptions.setTimeOut( timeout );
SimpleSelect select = new SimpleSelect( factory.getDialect() )
- .setLockMode( lockMode )
- .setTableName( lockable.getRootTableName() )
- .addColumn( lockable.getRootTableIdentifierColumnNames()[0] )
- .addCondition( lockable.getRootTableIdentifierColumnNames(), "=?" );
- if ( lockable.isVersioned() ) {
- select.addCondition( lockable.getVersionColumnName(), "=?" );
+ .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( lockMode + " lock " + lockable.getEntityName() );
+ select.setComment( getLockMode() + " lock " + getLockable().getEntityName() );
}
return select.toStatementString();
}
Modified: core/trunk/core/src/main/java/org/hibernate/engine/QueryParameters.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/engine/QueryParameters.java 2010-03-24 12:18:25 UTC (rev 19094)
+++ core/trunk/core/src/main/java/org/hibernate/engine/QueryParameters.java 2010-03-24 14:37:56 UTC (rev 19095)
@@ -272,6 +272,10 @@
return lockOptions;
}
+ public void setLockOptions(LockOptions lockOptions) {
+ this.lockOptions = lockOptions;
+ }
+
public void traceParameters(SessionFactoryImplementor factory) throws HibernateException {
Printer print = new Printer( factory );
if ( positionalParameterValues.length != 0 ) {
Modified: core/trunk/core/src/main/java/org/hibernate/event/def/DefaultLoadEventListener.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/event/def/DefaultLoadEventListener.java 2010-03-24 12:18:25 UTC (rev 19094)
+++ core/trunk/core/src/main/java/org/hibernate/event/def/DefaultLoadEventListener.java 2010-03-24 14:37:56 UTC (rev 19095)
@@ -496,7 +496,7 @@
Object entity = persister.load(
event.getEntityId(),
event.getInstanceToLoad(),
- event.getLockMode(),
+ event.getLockOptions(),
source
);
Modified: core/trunk/core/src/main/java/org/hibernate/loader/Loader.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/loader/Loader.java 2010-03-24 12:18:25 UTC (rev 19094)
+++ core/trunk/core/src/main/java/org/hibernate/loader/Loader.java 2010-03-24 14:37:56 UTC (rev 19095)
@@ -247,11 +247,10 @@
* persister from each row of the <tt>ResultSet</tt>. If an object is supplied, will attempt to
* initialize that object. If a collection is supplied, attempt to initialize that collection.
*/
- private List doQueryAndInitializeNonLazyCollections(final SessionImplementor session,
- final QueryParameters queryParameters,
- final boolean returnProxies)
- throws HibernateException, SQLException {
-
+ private List doQueryAndInitializeNonLazyCollections(
+ final SessionImplementor session,
+ final QueryParameters queryParameters,
+ final boolean returnProxies) throws HibernateException, SQLException {
final PersistenceContext persistenceContext = session.getPersistenceContext();
boolean defaultReadOnlyOrig = persistenceContext.isDefaultReadOnly();
if ( queryParameters.isReadOnlyInitialized() ) {
@@ -1628,6 +1627,24 @@
st.setFetchSize( selection.getFetchSize().intValue() );
}
}
+
+ // handle lock timeout...
+ LockOptions lockOptions = queryParameters.getLockOptions();
+ if ( lockOptions != null ) {
+ if ( lockOptions.getTimeOut() != LockOptions.WAIT_FOREVER ) {
+ if ( !dialect.supportsLockTimeouts() ) {
+ log.debug(
+ "Lock timeout [" + lockOptions.getTimeOut() +
+ "] requested but dialect reported to not support lock timeouts"
+ );
+ }
+ else if ( dialect.isLockTimeoutParameterized() ) {
+ st.setInt( col++, lockOptions.getTimeOut() );
+ }
+ }
+ }
+
+ log.trace( "Bound [" + col + "] parameters total" );
}
catch ( SQLException sqle ) {
session.getBatcher().closeQueryStatement( st, null );
@@ -1885,15 +1902,17 @@
/**
* Called by subclasses that load entities
* @param persister only needed for logging
+ * @param lockOptions
*/
protected final List loadEntity(
- final SessionImplementor session,
- final Object id,
- final Type identifierType,
- final Object optionalObject,
- final String optionalEntityName,
- final Serializable optionalIdentifier,
- final EntityPersister persister) throws HibernateException {
+ final SessionImplementor session,
+ final Object id,
+ final Type identifierType,
+ final Object optionalObject,
+ final String optionalEntityName,
+ final Serializable optionalIdentifier,
+ final EntityPersister persister,
+ LockOptions lockOptions) throws HibernateException {
if ( log.isDebugEnabled() ) {
log.debug(
@@ -1904,17 +1923,14 @@
List result;
try {
- result = doQueryAndInitializeNonLazyCollections(
- session,
- new QueryParameters(
- new Type[] { identifierType },
- new Object[] { id },
- optionalObject,
- optionalEntityName,
- optionalIdentifier
- ),
- false
- );
+ QueryParameters qp = new QueryParameters();
+ qp.setPositionalParameterTypes( new Type[] { identifierType } );
+ qp.setPositionalParameterValues( new Object[] { id } );
+ qp.setOptionalObject( optionalObject );
+ qp.setOptionalEntityName( optionalEntityName );
+ qp.setOptionalId( optionalIdentifier );
+ qp.setLockOptions( lockOptions );
+ result = doQueryAndInitializeNonLazyCollections( session, qp, false );
}
catch ( SQLException sqle ) {
final Loadable[] persisters = getEntityPersisters();
@@ -1951,14 +1967,14 @@
List result;
try {
- result = doQueryAndInitializeNonLazyCollections(
+ result = doQueryAndInitializeNonLazyCollections(
session,
- new QueryParameters(
+ new QueryParameters(
new Type[] { keyType, indexType },
new Object[] { key, index }
- ),
- false
- );
+ ),
+ false
+ );
}
catch ( SQLException sqle ) {
throw JDBCExceptionHelper.convert(
@@ -1978,15 +1994,17 @@
/**
* Called by wrappers that batch load entities
* @param persister only needed for logging
+ * @param lockOptions
*/
public final List loadEntityBatch(
- final SessionImplementor session,
- final Serializable[] ids,
- final Type idType,
- final Object optionalObject,
- final String optionalEntityName,
- final Serializable optionalId,
- final EntityPersister persister) throws HibernateException {
+ final SessionImplementor session,
+ final Serializable[] ids,
+ final Type idType,
+ final Object optionalObject,
+ final String optionalEntityName,
+ final Serializable optionalId,
+ final EntityPersister persister,
+ LockOptions lockOptions) throws HibernateException {
if ( log.isDebugEnabled() ) {
log.debug(
@@ -1999,11 +2017,14 @@
Arrays.fill( types, idType );
List result;
try {
- result = doQueryAndInitializeNonLazyCollections(
- session,
- new QueryParameters( types, ids, optionalObject, optionalEntityName, optionalId ),
- false
- );
+ QueryParameters qp = new QueryParameters();
+ qp.setPositionalParameterTypes( types );
+ qp.setPositionalParameterValues( ids );
+ qp.setOptionalObject( optionalObject );
+ qp.setOptionalEntityName( optionalEntityName );
+ qp.setOptionalId( optionalId );
+ qp.setLockOptions( lockOptions );
+ result = doQueryAndInitializeNonLazyCollections( session, qp, false );
}
catch ( SQLException sqle ) {
throw JDBCExceptionHelper.convert(
Modified: core/trunk/core/src/main/java/org/hibernate/loader/entity/AbstractEntityLoader.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/loader/entity/AbstractEntityLoader.java 2010-03-24 12:18:25 UTC (rev 19094)
+++ core/trunk/core/src/main/java/org/hibernate/loader/entity/AbstractEntityLoader.java 2010-03-24 14:37:56 UTC (rev 19095)
@@ -32,6 +32,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.HibernateException;
+import org.hibernate.LockOptions;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.engine.LoadQueryInfluencers;
@@ -60,13 +61,27 @@
}
- public Object load(Serializable id, Object optionalObject, SessionImplementor session)
- throws HibernateException {
- return load(session, id, optionalObject, id);
+ /**
+ * {@inheritDoc}
+ */
+ public Object load(Serializable id, Object optionalObject, SessionImplementor session) {
+ // this form is deprecated!
+ return load( id, optionalObject, session, LockOptions.NONE );
}
- protected Object load(SessionImplementor session, Object id, Object optionalObject, Serializable optionalId)
- throws HibernateException {
+ /**
+ * {@inheritDoc}
+ */
+ public Object load(Serializable id, Object optionalObject, SessionImplementor session, LockOptions lockOptions) {
+ return load( session, id, optionalObject, id, lockOptions );
+ }
+
+ protected Object load(
+ SessionImplementor session,
+ Object id,
+ Object optionalObject,
+ Serializable optionalId,
+ LockOptions lockOptions) {
List list = loadEntity(
session,
@@ -75,7 +90,8 @@
optionalObject,
entityName,
optionalId,
- persister
+ persister,
+ lockOptions
);
if ( list.size()==1 ) {
Modified: core/trunk/core/src/main/java/org/hibernate/loader/entity/BatchingEntityLoader.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/loader/entity/BatchingEntityLoader.java 2010-03-24 12:18:25 UTC (rev 19094)
+++ core/trunk/core/src/main/java/org/hibernate/loader/entity/BatchingEntityLoader.java 2010-03-24 14:37:56 UTC (rev 19095)
@@ -78,9 +78,15 @@
return null;
}
- public Object load(Serializable id, Object optionalObject, SessionImplementor session)
- throws HibernateException {
-
+ /**
+ * {@inheritDoc}
+ */
+ public Object load(Serializable id, Object optionalObject, SessionImplementor session) {
+ // this form is deprecated!
+ return load( id, optionalObject, session, LockOptions.NONE );
+ }
+
+ public Object load(Serializable id, Object optionalObject, SessionImplementor session, LockOptions lockOptions) {
Serializable[] batch = session.getPersistenceContext()
.getBatchFetchQueue()
.getEntityBatch( persister, id, batchSizes[0], session.getEntityMode() );
@@ -97,7 +103,8 @@
optionalObject,
persister.getEntityName(),
id,
- persister
+ persister,
+ lockOptions
);
return getObjectFromList(results, id, session); //EARLY EXIT
}
Modified: core/trunk/core/src/main/java/org/hibernate/loader/entity/EntityLoader.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/loader/entity/EntityLoader.java 2010-03-24 12:18:25 UTC (rev 19094)
+++ core/trunk/core/src/main/java/org/hibernate/loader/entity/EntityLoader.java 2010-03-24 14:37:56 UTC (rev 19095)
@@ -148,14 +148,16 @@
batchLoader = batchSize > 1;
- log.debug( "Static select for entity " + entityName + ": " + getSQLString() );
+ log.debug(
+ "Static select for entity " + entityName +
+ " [" + lockOptions.getLockMode() + ":" + lockOptions.getTimeOut() + "]: "
+ + getSQLString()
+ );
}
- public Object loadByUniqueKey(
- SessionImplementor session,
- Object key) throws HibernateException {
- return load( session, key, null, null );
+ public Object loadByUniqueKey(SessionImplementor session,Object key) {
+ return load( session, key, null, null, LockOptions.NONE );
}
protected boolean isSingleRowLoader() {
Modified: core/trunk/core/src/main/java/org/hibernate/loader/entity/UniqueEntityLoader.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/loader/entity/UniqueEntityLoader.java 2010-03-24 12:18:25 UTC (rev 19094)
+++ core/trunk/core/src/main/java/org/hibernate/loader/entity/UniqueEntityLoader.java 2010-03-24 14:37:56 UTC (rev 19095)
@@ -27,16 +27,37 @@
import java.io.Serializable;
import org.hibernate.HibernateException;
+import org.hibernate.LockOptions;
import org.hibernate.engine.SessionImplementor;
/**
* Loads entities for a <tt>EntityPersister</tt>
+ *
* @author Gavin King
+ * @author Steve Ebersole
*/
public interface UniqueEntityLoader {
/**
* Load an entity instance. If <tt>optionalObject</tt> is supplied,
* load the entity state into the given (uninitialized) object.
+ *
+ * @deprecated use {@link #load(java.io.Serializable, Object, SessionImplementor, LockOptions)} instead.
+ * @noinspection JavaDoc
*/
public Object load(Serializable id, Object optionalObject, SessionImplementor session) throws HibernateException;
+
+ /**
+ * Load an entity instance by id. If <tt>optionalObject</tt> is supplied (non-<tt>null</tt>,
+ * the entity state is loaded into that object instance instead of instantiating a new one.
+ *
+ * @param id The id to be loaded
+ * @param optionalObject The (optional) entity instance in to which to load the state
+ * @param session The session from which the request originated
+ * @param lockOptions The lock options.
+ *
+ * @return The loaded entity
+ *
+ * @throws HibernateException indicates problem performing the load.
+ */
+ public Object load(Serializable id, Object optionalObject, SessionImplementor session, LockOptions lockOptions);
}
Modified: core/trunk/core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java 2010-03-24 12:18:25 UTC (rev 19094)
+++ core/trunk/core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java 2010-03-24 14:37:56 UTC (rev 19095)
@@ -3248,18 +3248,8 @@
* Load an instance using either the <tt>forUpdateLoader</tt> or the outer joining <tt>loader</tt>,
* depending upon the value of the <tt>lock</tt> parameter
*/
- public Object load(Serializable id, Object optionalObject, LockMode lockMode, SessionImplementor session)
- throws HibernateException {
-
- if ( log.isTraceEnabled() ) {
- log.trace(
- "Fetching entity: " +
- MessageHelper.infoString( this, id, getFactory() )
- );
- }
-
- final UniqueEntityLoader loader = getAppropriateLoader( new LockOptions().setLockMode(lockMode), session );
- return loader.load( id, optionalObject, session );
+ public Object load(Serializable id, Object optionalObject, LockMode lockMode, SessionImplementor session) {
+ return load( id, optionalObject, new LockOptions().setLockMode(lockMode), session );
}
/**
@@ -3277,7 +3267,7 @@
}
final UniqueEntityLoader loader = getAppropriateLoader(lockOptions, session );
- return loader.load( id, optionalObject, session );
+ return loader.load( id, optionalObject, session, lockOptions );
}
public void registerAffectingFetchProfile(String fetchProfileName) {
@@ -3321,6 +3311,9 @@
// SQL query used for loading based on those influencers
return createEntityLoader(lockOptions, session.getLoadQueryInfluencers() );
}
+ else if ( lockOptions.getTimeOut() != LockOptions.WAIT_FOREVER ) {
+ return createEntityLoader( lockOptions, session.getLoadQueryInfluencers() );
+ }
else {
return ( UniqueEntityLoader ) loaders.get( lockOptions.getLockMode() );
}
Modified: core/trunk/core/src/main/java/org/hibernate/persister/entity/NamedQueryLoader.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/persister/entity/NamedQueryLoader.java 2010-03-24 12:18:25 UTC (rev 19094)
+++ core/trunk/core/src/main/java/org/hibernate/persister/entity/NamedQueryLoader.java 2010-03-24 14:37:56 UTC (rev 19095)
@@ -30,6 +30,7 @@
import org.slf4j.LoggerFactory;
import org.hibernate.FlushMode;
import org.hibernate.HibernateException;
+import org.hibernate.LockOptions;
import org.hibernate.engine.EntityKey;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.impl.AbstractQueryImpl;
@@ -38,7 +39,9 @@
/**
* Not really a <tt>Loader</tt>, just a wrapper around a
* named query.
+ *
* @author Gavin King
+ * @author Steve Ebersole
*/
public final class NamedQueryLoader implements UniqueEntityLoader {
private final String queryName;
@@ -52,9 +55,14 @@
this.persister = persister;
}
- public Object load(Serializable id, Object optionalObject, SessionImplementor session)
- throws HibernateException {
-
+ public Object load(Serializable id, Object optionalObject, SessionImplementor session, LockOptions lockOptions) {
+ if ( lockOptions != null ) {
+ log.debug( "Ignoring lock-options passed to named query loader" );
+ }
+ return load( id, optionalObject, session );
+ }
+
+ public Object load(Serializable id, Object optionalObject, SessionImplementor session) {
if ( log.isDebugEnabled() ) {
log.debug(
"loading entity: " + persister.getEntityName() +
Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java 2010-03-24 12:18:25 UTC (rev 19094)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java 2010-03-24 14:37:56 UTC (rev 19095)
@@ -216,14 +216,14 @@
timeout = Integer.parseInt( ( String ) lockTimeout );
timeoutSet = true;
}
- else if ( lockTimeout instanceof Integer ) {
- timeout = ( Integer ) lockTimeout;
+ else if ( lockTimeout instanceof Number ) {
+ timeout = ( (Number) lockTimeout ).intValue();
timeoutSet = true;
}
else if ( lockTimeout != null ) {
throw new PersistenceException( "Unable to parse " + AvailableSettings.LOCK_TIMEOUT + ": " + lockTimeout );
}
- if ( timeoutSet != false ) {
+ if ( timeoutSet ) {
if ( timeout < 0 ) {
options.setTimeOut( LockOptions.WAIT_FOREVER );
}
Modified: core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/lock/LockTest.java
===================================================================
--- core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/lock/LockTest.java 2010-03-24 12:18:25 UTC (rev 19094)
+++ core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/lock/LockTest.java 2010-03-24 14:37:56 UTC (rev 19095)
@@ -12,6 +12,7 @@
import org.apache.commons.logging.LogFactory;
import org.hibernate.dialect.HSQLDialect;
import org.hibernate.dialect.Oracle10gDialect;
+import org.hibernate.ejb.AvailableSettings;
import org.hibernate.ejb.test.TestCase;
import java.util.HashMap;
@@ -26,8 +27,33 @@
* @author Emmanuel Bernard
*/
public class LockTest extends TestCase {
+ private static final Log log = LogFactory.getLog( LockTest.class );
- private static final Log log = LogFactory.getLog( LockTest.class );
+ public void testFindWithTimeoutHint() {
+ EntityManager em = getOrCreateEntityManager();
+ em.getTransaction().begin();
+ Lock lock = new Lock();
+ lock.setName( "name" );
+ em.persist( lock );
+ em.getTransaction().commit();
+ em.close();
+
+ em = getOrCreateEntityManager();
+ em.getTransaction().begin();
+ Map<String, Object> properties = new HashMap<String, Object>();
+ properties.put( AvailableSettings.LOCK_TIMEOUT, 0L );
+ em.find( Lock.class, 1, LockModeType.PESSIMISTIC_WRITE, properties );
+ em.getTransaction().commit();
+ em.close();
+
+ em = getOrCreateEntityManager();
+ em.getTransaction().begin();
+ lock = em.find( Lock.class, lock.getId() );
+ em.remove( lock );
+ em.getTransaction().commit();
+ em.close();
+ }
+
public void testLockRead() throws Exception {
Lock lock = new Lock();
lock.setName( "name" );
More information about the hibernate-commits
mailing list