[hibernate-commits] Hibernate SVN: r18675 - in core/trunk: core/src/main/java/org/hibernate/hql/classic and 7 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Mon Feb 1 14:42:18 EST 2010


Author: steve.ebersole at jboss.com
Date: 2010-02-01 14:42:16 -0500 (Mon, 01 Feb 2010)
New Revision: 18675

Added:
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/util/LockModeTypeHelper.java
Modified:
   core/trunk/core/src/main/java/org/hibernate/LockOptions.java
   core/trunk/core/src/main/java/org/hibernate/hql/classic/QueryTranslatorImpl.java
   core/trunk/core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java
   core/trunk/core/src/main/java/org/hibernate/impl/AbstractQueryImpl.java
   core/trunk/core/src/main/java/org/hibernate/impl/QueryImpl.java
   core/trunk/core/src/main/java/org/hibernate/loader/criteria/CriteriaLoader.java
   core/trunk/core/src/main/java/org/hibernate/loader/criteria/CriteriaQueryTranslator.java
   core/trunk/core/src/main/java/org/hibernate/loader/hql/QueryLoader.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractQueryImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AvailableSettings.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/QueryImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/util/CacheModeHelper.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/dialect/unit/lockhint/AbstractLockHintTest.java
Log:
HHH-4661 - Properly propagate Query.setLockMode to Hibernate Core


Modified: core/trunk/core/src/main/java/org/hibernate/LockOptions.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/LockOptions.java	2010-01-31 21:50:23 UTC (rev 18674)
+++ core/trunk/core/src/main/java/org/hibernate/LockOptions.java	2010-02-01 19:42:16 UTC (rev 18675)
@@ -35,17 +35,8 @@
  * 
  * @author Scott Marlow
  */
-public class LockOptions implements Serializable
-{
+public class LockOptions implements Serializable {
 	/**
-	 * NO_WAIT timeout value will not block for pessimistic locking
-	 */
-	public static final int NO_WAIT = 0;
-	/**
-	 * WAIT_FOREVER timeout value will block until pessimistic lock is obtained
-	 */
-	public static final int WAIT_FOREVER = -1;
-	/**
 	 * NONE represents LockMode.NONE (timeout + scope do not apply)
 	 */
 	public static final LockOptions NONE = new LockOptions(LockMode.NONE);
@@ -59,15 +50,6 @@
 	 */
 	public static final LockOptions UPGRADE = new LockOptions(LockMode.UPGRADE);
 
-	private LockMode lockMode = LockMode.NONE;
-
-	private int timeout = WAIT_FOREVER;	// timeout in milliseconds, 0 = no wait, -1 = wait indefinitely
-
-	private boolean scope=false;// if true, cascade (pessimistic only) lock to collections and relationships
-										 // owned by the entity.
-
-	private Map /* <String, LockMode> */ lockModesByName = new HashMap();
-
 	public LockOptions() {
 	}
 
@@ -75,110 +57,173 @@
 		this.lockMode = lockMode;
 	}
 
+	private LockMode lockMode = LockMode.NONE;
+
 	/**
-	 * Get the lock mode.
-	 * @return the lock mode.
+	 * Retrieve the overall lock mode in effect for this set of options.
+	 * <p/>
+	 * In certain contexts (hql and criteria), lock-modes can be defined in an
+	 * even more granular {@link #setAliasSpecificLockMode(String, LockMode) per-alias} fashion
+	 *
+	 * @return The overall lock mode.
 	 */
 	public LockMode getLockMode() {
 		return lockMode;
 	}
 
 	/**
-	 * Specify the LockMode to be used.  The default is LockMode.none.
+	 * Set the overall {@link LockMode} to be used.  The default is
+	 * {@link LockMode#NONE}
 	 *
-	 * @param lockMode
-	 * @return this LockRequest instance for operation chaining.
+	 * @param lockMode The new overall lock mode to use.
+	 *
+	 * @return this (for method chaining).
 	 */
 	public LockOptions setLockMode(LockMode lockMode) {
 		this.lockMode = lockMode;
 		return this;
 	}
 
+	private Map aliasSpecificLockModes = new HashMap();
+
 	/**
-	 * Specify the LockMode to be used for the specified alias.
+	 * Specify the {@link LockMode} to be used for a specific query alias.
 	 *
-	 * The ability to set the lockMode for a table alias is intended
-	 * for internal Hibernate use.
-	 *
-	 * @param lockMode
 	 * @param alias used to reference the LockMode.
+	 * @param lockMode The lock mode to apply to the given alias
 	 * @return this LockRequest instance for operation chaining.
+	 *
+	 * @see Query#setLockMode(String, LockMode)
+	 * @see Criteria#setLockMode(LockMode)
+	 * @see Criteria#setLockMode(String, LockMode)
 	 */
-	public LockOptions setAliasLockMode(LockMode lockMode, String alias) {
-		lockModesByName.put(alias, lockMode);
+	public LockOptions setAliasSpecificLockMode(String alias, LockMode lockMode) {
+		aliasSpecificLockModes.put( alias, lockMode );
 		return this;
 	}
 
 	/**
-	 * Get the lock mode for the specified alias.
+	 * Get the {@link LockMode} explicitly specified for the given alias via
+	 * {@link #setAliasSpecificLockMode}
+	 * <p/>
+	 * Differs from {@link #getEffectiveLockMode} in that here we only return
+	 * explicitly specified alias-specific lock modes.
 	 *
-	 * @param alias used to reference the LockMode.
-	 * @return the lock mode.
+	 * @param alias The alias for which to locate the explicit lock mode.
+	 *
+	 * @return The explicit lock mode for that alias.
 	 */
-	public LockMode getAliasLockMode(String alias) {
-		return (LockMode)lockModesByName.get(alias);
+	public LockMode getAliasSpecificLockMode(String alias) {
+		return (LockMode) aliasSpecificLockModes.get( alias );
 	}
 
 	/**
-	 * Get the number of aliases that have LockModes specified
+	 * Determine the {@link LockMode} to apply to the given alias.  If no
+	 * mode was explicitly {@link #setAliasSpecificLockMode set}, the
+	 * {@link #getLockMode overall mode} is returned.  If the overall lock mode is
+	 * <tt>null</tt> as well, {@link LockMode#NONE} is returned.
+	 * <p/>
+	 * Differs from {@link #getAliasSpecificLockMode} in that here we fallback to we only return
+	 * the overall lock mode.
 	 *
-	 * @return the number of aliases
+	 * @param alias The alias for which to locate the effective lock mode.
+	 *
+	 * @return The effective lock mode.
 	 */
+	public LockMode getEffectiveLockMode(String alias) {
+		LockMode lockMode = getAliasSpecificLockMode( alias );
+		if ( lockMode == null ) {
+			lockMode = this.lockMode;
+		}
+		return lockMode == null ? LockMode.NONE : lockMode;
+	}
+
+	/**
+	 * Get the number of aliases that have specific lock modes defined.
+	 *
+	 * @return the number of explicitly defined alias lock modes.
+	 */
 	public int getAliasLockCount() {
-		return lockModesByName.size();
+		return aliasSpecificLockModes.size();
 	}
 
 	/**
 	 * Iterator for accessing Alias (key) and LockMode (value) as Map.Entry
-	 * 
+	 *
 	 * @return Iterator for accessing the Map.Entry's
 	 */
 	public Iterator getAliasLockIterator() {
-		return lockModesByName.entrySet().iterator();
+		return aliasSpecificLockModes.entrySet().iterator();
 	}
 
 	/**
-	 * Get the timeout setting.
+	 * Indicates that the database should not wait at all to acquire the pessimistic lock.
+	 * @see #getTimeOut
+	 */
+	public static final int NO_WAIT = 0;
+	/**
+	 * Indicates that there is no timeout for the acquisition.
+	 * @see #getTimeOut
+	 */
+	public static final int WAIT_FOREVER = -1;
+
+	private int timeout = WAIT_FOREVER;
+
+	/**
+	 * Retrieve the current timeout setting.
+	 * <p/>
+	 * The timeout is the amount of time, in milliseconds, we should instruct the database
+	 * to wait for any requested pessimistic lock acquisition.
+	 * <p/>
+	 * {@link #NO_WAIT} and {@link #WAIT_FOREVER} represent 2 "magic" values.
 	 *
-	 * @return timeout in milliseconds, -1 for indefinite wait and 0 for no wait.
+	 * @return timeout in milliseconds, or {@link #NO_WAIT} or {@link #WAIT_FOREVER}
 	 */
 	public int getTimeOut() {
 		return timeout;
 	}
 
 	/**
-	 * Specify the pessimistic lock timeout (check if your dialect supports this option).
-	 * The default pessimistic lock behavior is to wait forever for the lock.
+	 * Set the timeout setting.
+	 * <p/>
+	 * See {@link #getTimeOut} for a discussion of meaning.
 	 *
-	 * @param timeout is time in milliseconds to wait for lock.  -1 means wait forever and 0 means no wait.
-	 * @return this LockRequest instance for operation chaining.
+	 * @param timeout The new timeout setting.
+	 *
+	 * @return this (for method chaining).
+	 *
+	 * @see #getTimeOut
 	 */
 	public LockOptions setTimeOut(int timeout) {
 		this.timeout = timeout;
 		return this;
 	}
 
+	private boolean scope=false;
+
 	/**
-	 * Check if locking is cascaded to owned collections and relationships.
-	 * @return true if locking will be extended to owned collections and relationships.
+	 * Retrieve the current lock scope setting.
+	 * <p/>
+	 * "scope" is a JPA defined term.  It is basically a cascading of the lock to associations.
+	 *
+	 * @return true if locking will be extended to owned associations
 	 */
 	public boolean getScope() {
 		return scope;
 	}
 
 	/**
-	 * Specify if LockMode should be cascaded to owned collections and relationships.
-	 * The association must be mapped with <tt>cascade="lock" for scope=true to work.
+	 * Set the cope.
 	 *
-	 * @param scope
-	 * @return
+	 * @param scope The new scope setting
+	 *
+	 * @return this (for method chaining).
 	 */
 	public LockOptions setScope(boolean scope) {
 		this.scope = scope;
 		return this;
 	}
 
-
 	/**
 	 * Shallow copy From to Dest
 	 *
@@ -190,7 +235,7 @@
 		dest.setLockMode(from.getLockMode());
 		dest.setScope(from.getScope());
 		dest.setTimeOut(from.getTimeOut());
-		dest.lockModesByName = new HashMap(from.lockModesByName);
+		dest.aliasSpecificLockModes = new HashMap(from.aliasSpecificLockModes );
 		return dest;
 	}
 }

Modified: core/trunk/core/src/main/java/org/hibernate/hql/classic/QueryTranslatorImpl.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/hql/classic/QueryTranslatorImpl.java	2010-01-31 21:50:23 UTC (rev 18674)
+++ core/trunk/core/src/main/java/org/hibernate/hql/classic/QueryTranslatorImpl.java	2010-02-01 19:42:16 UTC (rev 18675)
@@ -1080,7 +1080,7 @@
 			Iterator iter = lockOptions.getAliasLockIterator();
 			while ( iter.hasNext() ) {
 				Map.Entry me = ( Map.Entry ) iter.next();
-				locks.setAliasLockMode( (LockMode) me.getValue(),  getAliasName( ( String ) me.getKey() ) );
+				locks.setAliasSpecificLockMode( getAliasName( ( String ) me.getKey() ), (LockMode) me.getValue() );
 			}
 			Map keyColumnNames = null;
 			if ( dialect.forUpdateOfColumns() ) {

Modified: core/trunk/core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java	2010-01-31 21:50:23 UTC (rev 18674)
+++ core/trunk/core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java	2010-02-01 19:42:16 UTC (rev 18675)
@@ -429,7 +429,7 @@
 				" from " + tableName + ' ' + alias +
 				" where " + StringHelper.qualify( alias, segmentColumnName ) + "=?";
 		LockOptions lockOptions = new LockOptions(LockMode.UPGRADE);
-		lockOptions.setAliasLockMode(LockMode.UPGRADE, alias);
+		lockOptions.setAliasSpecificLockMode( alias, LockMode.UPGRADE );
 		Map updateTargetColumnsMap = Collections.singletonMap( alias, new String[] { valueColumnName } );
 		return dialect.applyLocksToSql( query, lockOptions, updateTargetColumnsMap );
 	}

Modified: core/trunk/core/src/main/java/org/hibernate/impl/AbstractQueryImpl.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/impl/AbstractQueryImpl.java	2010-01-31 21:50:23 UTC (rev 18674)
+++ core/trunk/core/src/main/java/org/hibernate/impl/AbstractQueryImpl.java	2010-02-01 19:42:16 UTC (rev 18675)
@@ -241,7 +241,7 @@
 		return session;
 	}
 
-	protected abstract LockOptions getLockOptions();
+	public abstract LockOptions getLockOptions();
 
 
 	// Parameter handling code ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Modified: core/trunk/core/src/main/java/org/hibernate/impl/QueryImpl.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/impl/QueryImpl.java	2010-01-31 21:50:23 UTC (rev 18674)
+++ core/trunk/core/src/main/java/org/hibernate/impl/QueryImpl.java	2010-02-01 19:42:16 UTC (rev 18675)
@@ -125,7 +125,7 @@
 	}
 
 	public Query setLockMode(String alias, LockMode lockMode) {
-		lockOptions.setAliasLockMode(lockMode, alias);
+		lockOptions.setAliasSpecificLockMode( alias, lockMode );
 		return this;
 	}
 	
@@ -136,7 +136,7 @@
 		return this;
 	}
 
-	protected LockOptions getLockOptions() {
+	public LockOptions getLockOptions() {
 		return lockOptions;
 	}
 

Modified: core/trunk/core/src/main/java/org/hibernate/loader/criteria/CriteriaLoader.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/loader/criteria/CriteriaLoader.java	2010-01-31 21:50:23 UTC (rev 18674)
+++ core/trunk/core/src/main/java/org/hibernate/loader/criteria/CriteriaLoader.java	2010-02-01 19:42:16 UTC (rev 18675)
@@ -157,11 +157,11 @@
 		final Map keyColumnNames = dialect.forUpdateOfColumns() ? new HashMap() : null;
 		final String[] drivingSqlAliases = getAliases();
 		for ( int i = 0; i < drivingSqlAliases.length; i++ ) {
-			final LockMode lockMode = lockOptions.getAliasLockMode( drivingSqlAliases[i] );
+			final LockMode lockMode = lockOptions.getAliasSpecificLockMode( drivingSqlAliases[i] );
 			if ( lockMode != null ) {
 				final Lockable drivingPersister = ( Lockable ) getEntityPersisters()[i];
 				final String rootSqlAlias = drivingPersister.getRootTableAlias( drivingSqlAliases[i] );
-				locks.setAliasLockMode(lockMode, rootSqlAlias);
+				locks.setAliasSpecificLockMode( rootSqlAlias, lockMode );
 				if ( keyColumnNames != null ) {
 					keyColumnNames.put( rootSqlAlias, drivingPersister.getRootTableIdentifierColumnNames() );
 				}
@@ -178,7 +178,7 @@
 		final int size = entityAliases.length;
 		LockMode[] lockModesArray = new LockMode[size];
 		for ( int i=0; i<size; i++ ) {
-			LockMode lockMode = lockOptions.getAliasLockMode( entityAliases[i] );
+			LockMode lockMode = lockOptions.getAliasSpecificLockMode( entityAliases[i] );
 			lockModesArray[i] = lockMode==null ? lockOptions.getLockMode() : lockMode;
 		}
 		return lockModesArray;

Modified: core/trunk/core/src/main/java/org/hibernate/loader/criteria/CriteriaQueryTranslator.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/loader/criteria/CriteriaQueryTranslator.java	2010-01-31 21:50:23 UTC (rev 18674)
+++ core/trunk/core/src/main/java/org/hibernate/loader/criteria/CriteriaQueryTranslator.java	2010-02-01 19:42:16 UTC (rev 18675)
@@ -284,7 +284,7 @@
 		while ( iter.hasNext() ) {
 			Map.Entry me = ( Map.Entry ) iter.next();
 			final Criteria subcriteria = getAliasedCriteria( ( String ) me.getKey() );
-			lockOptions.setAliasLockMode( (LockMode)me.getValue(), getSQLAlias( subcriteria ) );
+			lockOptions.setAliasSpecificLockMode( getSQLAlias( subcriteria ), (LockMode)me.getValue() );
 		}
 		List values = new ArrayList();
 		List types = new ArrayList();
@@ -293,7 +293,7 @@
 			CriteriaImpl.Subcriteria subcriteria = ( CriteriaImpl.Subcriteria ) iter.next();
 			LockMode lm = subcriteria.getLockMode();
 			if ( lm != null ) {
-				lockOptions.setAliasLockMode( lm, getSQLAlias( subcriteria ) );
+				lockOptions.setAliasSpecificLockMode( getSQLAlias( subcriteria ), lm );
 			}
 			if ( subcriteria.getWithClause() != null )
 			{

Modified: core/trunk/core/src/main/java/org/hibernate/loader/hql/QueryLoader.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/loader/hql/QueryLoader.java	2010-01-31 21:50:23 UTC (rev 18674)
+++ core/trunk/core/src/main/java/org/hibernate/loader/hql/QueryLoader.java	2010-02-01 19:42:16 UTC (rev 18675)
@@ -28,6 +28,7 @@
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -292,10 +293,10 @@
 
 			LockMode[] lockModesArray = new LockMode[entityAliases.length];
 			for ( int i = 0; i < entityAliases.length; i++ ) {
-				LockMode lockMode = lockOptions.getAliasLockMode( entityAliases[i] );
+				LockMode lockMode = lockOptions.getEffectiveLockMode( entityAliases[i] );
 				if ( lockMode == null ) {
 					//NONE, because its the requested lock mode, not the actual! 
-					lockMode = lockOptions.getLockMode();
+					lockMode = LockMode.NONE;
 				}
 				lockModesArray[i] = lockMode;
 			}
@@ -312,16 +313,16 @@
 		// can't cache this stuff either (per-invocation)
 		// we are given a map of user-alias -> lock mode
 		// create a new map of sql-alias -> lock mode
-		final LockOptions locks = new LockOptions(lockOptions.getLockMode());
-		locks.setScope( lockOptions.getScope());
-		locks.setTimeOut( lockOptions.getTimeOut());
+		final LockOptions locks = new LockOptions( lockOptions.getLockMode() );
+		locks.setScope( lockOptions.getScope() );
+		locks.setTimeOut( lockOptions.getTimeOut() );
 
 		final Map keyColumnNames = dialect.forUpdateOfColumns() ? new HashMap() : null;
-		final Iterator iter = lockOptions.getAliasLockIterator();
-		while ( iter.hasNext() ) {
-			Map.Entry me = ( Map.Entry ) iter.next();
-			final String userAlias = ( String ) me.getKey();
-			final String drivingSqlAlias = ( String ) sqlAliasByEntityAlias.get( userAlias );
+		final Iterator itr = sqlAliasByEntityAlias.entrySet().iterator();
+		while ( itr.hasNext() ) {
+			final Map.Entry entry = (Map.Entry) itr.next();
+			final String userAlias = (String) entry.getKey();
+			final String drivingSqlAlias = (String) entry.getValue();
 			if ( drivingSqlAlias == null ) {
 				throw new IllegalArgumentException( "could not locate alias to apply lock mode : " + userAlias );
 			}
@@ -334,11 +335,15 @@
 			final QueryNode select = ( QueryNode ) queryTranslator.getSqlAST();
 			final Lockable drivingPersister = ( Lockable ) select.getFromClause().getFromElement( userAlias ).getQueryable();
 			final String sqlAlias = drivingPersister.getRootTableAlias( drivingSqlAlias );
-			locks.setAliasLockMode( (LockMode)me.getValue(), sqlAlias);
+
+			final LockMode effectiveLockMode = lockOptions.getEffectiveLockMode( userAlias );
+			locks.setAliasSpecificLockMode( sqlAlias, effectiveLockMode );
+
 			if ( keyColumnNames != null ) {
 				keyColumnNames.put( sqlAlias, drivingPersister.getRootTableIdentifierColumnNames() );
 			}
 		}
+
 		return dialect.applyLocksToSql( sql, locks, keyColumnNames );
 	}
 

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java	2010-01-31 21:50:23 UTC (rev 18674)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java	2010-02-01 19:42:16 UTC (rev 18675)
@@ -92,6 +92,7 @@
 import org.hibernate.ejb.transaction.JoinableCMTTransaction;
 import org.hibernate.ejb.util.CacheModeHelper;
 import org.hibernate.ejb.util.ConfigurationHelper;
+import org.hibernate.ejb.util.LockModeTypeHelper;
 import org.hibernate.engine.SessionFactoryImplementor;
 import org.hibernate.engine.SessionImplementor;
 import org.hibernate.proxy.HibernateProxy;
@@ -851,52 +852,13 @@
 
 	@SuppressWarnings("deprecation")
 	private static LockModeType getLockModeType(LockMode lockMode) {
-		if ( lockMode == LockMode.NONE )
-			return LockModeType.NONE;
-		else if ( lockMode == LockMode.OPTIMISTIC || lockMode == LockMode.READ )
-			return LockModeType.OPTIMISTIC;
-		else if ( lockMode == LockMode.OPTIMISTIC_FORCE_INCREMENT || lockMode == LockMode.WRITE )
-			return LockModeType.OPTIMISTIC_FORCE_INCREMENT;
-		else if ( lockMode == LockMode.PESSIMISTIC_READ )
-			return LockModeType.PESSIMISTIC_READ;
-		else if ( lockMode == LockMode.PESSIMISTIC_WRITE
-				|| lockMode == LockMode.UPGRADE
-				|| lockMode == LockMode.UPGRADE_NOWAIT) //timeout of 0
-			//TODO check that if we have UPGRADE_NOWAIT we have a timeout of zero?
-			return LockModeType.PESSIMISTIC_WRITE;
-		else if ( lockMode == LockMode.PESSIMISTIC_FORCE_INCREMENT
-				|| lockMode == LockMode.FORCE)
-			return LockModeType.PESSIMISTIC_FORCE_INCREMENT;
-		throw new AssertionFailure("unhandled lock mode " + lockMode );
+		//TODO check that if we have UPGRADE_NOWAIT we have a timeout of zero?
+		return LockModeTypeHelper.getLockModeType( lockMode );
 	}
 
 
 	private static LockMode getLockMode(LockModeType lockMode) {
-		switch ( lockMode ) {
-
-			case READ:
-			case OPTIMISTIC:
-				return LockMode.OPTIMISTIC;
-
-			case OPTIMISTIC_FORCE_INCREMENT:
-			case WRITE:
-				return LockMode.OPTIMISTIC_FORCE_INCREMENT;
-
-			case PESSIMISTIC_READ:
-				return LockMode.PESSIMISTIC_READ;
-
-			case PESSIMISTIC_WRITE:
-				return LockMode.PESSIMISTIC_WRITE;
-
-			case PESSIMISTIC_FORCE_INCREMENT:
-				return LockMode.PESSIMISTIC_FORCE_INCREMENT;
-
-			case NONE:
-				return LockMode.NONE;
-
-			default:
-				throw new AssertionFailure( "Unknown LockModeType: " + lockMode );
-		}
+		return LockModeTypeHelper.getLockMode( lockMode );
 	}
 
 	public boolean isTransactionInProgress() {

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractQueryImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractQueryImpl.java	2010-01-31 21:50:23 UTC (rev 18674)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractQueryImpl.java	2010-02-01 19:42:16 UTC (rev 18675)
@@ -40,6 +40,7 @@
 import org.hibernate.CacheMode;
 import org.hibernate.FlushMode;
 import org.hibernate.HibernateException;
+import org.hibernate.LockMode;
 import org.hibernate.TypeMismatchException;
 import static org.hibernate.ejb.QueryHints.HINT_CACHEABLE;
 import static org.hibernate.ejb.QueryHints.HINT_CACHE_MODE;
@@ -52,6 +53,7 @@
 
 import org.hibernate.ejb.util.CacheModeHelper;
 import org.hibernate.ejb.util.ConfigurationHelper;
+import org.hibernate.ejb.util.LockModeTypeHelper;
 import org.hibernate.hql.QueryExecutionRequestException;
 
 /**
@@ -189,6 +191,10 @@
 
 	protected abstract void applyFlushMode(FlushMode flushMode);
 
+	protected abstract boolean canApplyLockModes();
+
+	protected abstract void applyAliasSpecificLockMode(String alias, LockMode lockMode);
+
 	/**
 	 * {@inheritDoc}
 	 */
@@ -247,10 +253,24 @@
 						CacheModeHelper.interpretCacheMode( storeMode, retrieveMode )
 				);
 			}
-			/* TODO:
-			else if ( "org.hibernate.lockMode".equals( hintName ) ) {
-				query.setAliasLockMode( alias, lockMode );
-			}*/
+			else if ( hintName.startsWith( AvailableSettings.ALIAS_SPECIFIC_LOCK_MODE ) ) {
+				if ( ! canApplyLockModes() ) {
+					skipped = true;
+				}
+				else {
+					// extract the alias
+					final String alias = hintName.substring( AvailableSettings.ALIAS_SPECIFIC_LOCK_MODE.length() );
+					// determine the LockMode
+					try {
+						final LockMode lockMode = LockModeTypeHelper.interpretLockMode( value );
+						applyAliasSpecificLockMode( alias, lockMode );
+					}
+					catch ( Exception e ) {
+						log.info( "Unable to determine lock mode value : {} -> {}", hintName, value );
+						skipped = true;
+					}
+				}
+			}
 			else {
 				skipped = true;
 				log.info( "Ignoring unrecognized query hint [" + hintName + "]" );

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AvailableSettings.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AvailableSettings.java	2010-01-31 21:50:23 UTC (rev 18674)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AvailableSettings.java	2010-02-01 19:42:16 UTC (rev 18675)
@@ -192,6 +192,20 @@
 	// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 	/**
+	 * Query hint (aka {@link javax.persistence.Query#setHint}) for applying
+	 * an alias specific lock mode (aka {@link org.hibernate.Query#setLockMode}).
+	 * <p/>
+	 * Either {@link org.hibernate.LockMode} or {@link javax.persistence.LockModeType}
+	 * are accepted.  Also the String names of either are accepted as well.  <tt>null</tt>
+	 * is additionally accepted as meaning {@link org.hibernate.LockMode#NONE}.
+	 * <p/>
+	 * Usage is to concatenate this setting name and the alias name together, separated
+	 * by a dot.  For example<code>Query.setHint( "org.hibernate.lockMode.a", someLockMode )</code>
+	 * would apply <code>someLockMode</code> to the alias <code>"a"</code>.
+	 */
+	public static final String ALIAS_SPECIFIC_LOCK_MODE = "org.hibernate.lockMode";
+
+	/**
 	 * JAR autodetection artifacts class, hbm
 	 */
 	public static final String AUTODETECTION = "hibernate.archive.autodetection";

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java	2010-01-31 21:50:23 UTC (rev 18674)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java	2010-02-01 19:42:16 UTC (rev 18675)
@@ -107,7 +107,7 @@
 	public PersistenceException wrapStaleStateException(StaleStateException e);
 
 	/**
-	 * Convert from JPA-2 LockModeType & properties into LockOptions
+	 * Convert from JPA 2 {@link LockModeType} & properties into {@link LockOptions}
 	 *
 	 * @param lockModeType is the requested lock type
 	 * @param properties are the lock properties

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/QueryImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/QueryImpl.java	2010-01-31 21:50:23 UTC (rev 18674)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/QueryImpl.java	2010-02-01 19:42:16 UTC (rev 18675)
@@ -50,10 +50,11 @@
 import org.hibernate.CacheMode;
 import org.hibernate.FlushMode;
 import org.hibernate.HibernateException;
+import org.hibernate.LockMode;
 import org.hibernate.QueryParameterException;
 import org.hibernate.TypeMismatchException;
 import org.hibernate.SQLQuery;
-import org.hibernate.LockOptions;
+import org.hibernate.ejb.util.LockModeTypeHelper;
 import org.hibernate.engine.query.NamedParameterDescriptor;
 import org.hibernate.engine.query.OrdinalParameterDescriptor;
 import org.hibernate.hql.QueryExecutionRequestException;
@@ -217,6 +218,15 @@
 		query.setFlushMode( flushMode );
 	}
 
+	protected boolean canApplyLockModes() {
+		return org.hibernate.impl.QueryImpl.class.isInstance( query );
+	}
+
+	@Override
+	protected void applyAliasSpecificLockMode(String alias, LockMode lockMode) {
+		( (org.hibernate.impl.QueryImpl) query ).getLockOptions().setAliasSpecificLockMode( alias, lockMode );
+	}
+
 	/**
 	 * {@inheritDoc}
 	 */
@@ -590,13 +600,16 @@
 
 	@SuppressWarnings({ "unchecked" })
 	public TypedQuery<X> setLockMode(javax.persistence.LockModeType lockModeType) {
-
 		if (! getEntityManager().isTransactionInProgress()) {
 			throw new TransactionRequiredException( "no transaction is in progress" );
 		}
-
+		if ( ! canApplyLockModes() ) {
+			throw new IllegalStateException( "Not a JPAQL/Criteria query" );
+		}
 		this.jpaLockMode = lockModeType;
-		query.setLockOptions(getEntityManager().getLockRequest(lockModeType, null));
+		( (org.hibernate.impl.QueryImpl) query ).getLockOptions().setLockMode(
+				LockModeTypeHelper.getLockMode( lockModeType )
+		);
 		return this;
 	}
 

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/util/CacheModeHelper.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/util/CacheModeHelper.java	2010-01-31 21:50:23 UTC (rev 18674)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/util/CacheModeHelper.java	2010-02-01 19:42:16 UTC (rev 18675)
@@ -29,7 +29,8 @@
 import org.hibernate.CacheMode;
 
 /**
- * TODO : javadoc
+ * Helper to deal with {@link CacheMode} <-> {@link CacheRetrieveMode}/{@link CacheStoreMode}
+ * conversions.
  *
  * @author Steve Ebersole
  */

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/util/LockModeTypeHelper.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/util/LockModeTypeHelper.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/util/LockModeTypeHelper.java	2010-02-01 19:42:16 UTC (rev 18675)
@@ -0,0 +1,119 @@
+/*
+ * 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.ejb.util;
+
+import javax.persistence.LockModeType;
+
+import org.hibernate.AssertionFailure;
+import org.hibernate.LockMode;
+
+/**
+ * Helper to deal with {@link LockModeType} <-> {@link LockMode} conversions.
+ *
+ * @author Steve Ebersole
+ */
+public class LockModeTypeHelper {
+	public static LockModeType getLockModeType(LockMode lockMode) {
+		if ( lockMode == LockMode.NONE ) {
+			return LockModeType.NONE;
+		}
+		else if ( lockMode == LockMode.OPTIMISTIC || lockMode == LockMode.READ ) {
+			return LockModeType.OPTIMISTIC;
+		}
+		else if ( lockMode == LockMode.OPTIMISTIC_FORCE_INCREMENT || lockMode == LockMode.WRITE ) {
+			return LockModeType.OPTIMISTIC_FORCE_INCREMENT;
+		}
+		else if ( lockMode == LockMode.PESSIMISTIC_READ ) {
+			return LockModeType.PESSIMISTIC_READ;
+		}
+		else if ( lockMode == LockMode.PESSIMISTIC_WRITE
+				|| lockMode == LockMode.UPGRADE
+				|| lockMode == LockMode.UPGRADE_NOWAIT ) {
+			return LockModeType.PESSIMISTIC_WRITE;
+		}
+		else if ( lockMode == LockMode.PESSIMISTIC_FORCE_INCREMENT
+				|| lockMode == LockMode.FORCE ) {
+			return LockModeType.PESSIMISTIC_FORCE_INCREMENT;
+		}
+		throw new AssertionFailure( "unhandled lock mode " + lockMode );
+	}
+
+
+	public static LockMode getLockMode(LockModeType lockMode) {
+		switch ( lockMode ) {
+			case READ:
+			case OPTIMISTIC: {
+				return LockMode.OPTIMISTIC;
+			}
+			case OPTIMISTIC_FORCE_INCREMENT:
+			case WRITE: {
+				return LockMode.OPTIMISTIC_FORCE_INCREMENT;
+			}
+			case PESSIMISTIC_READ: {
+				return LockMode.PESSIMISTIC_READ;
+			}
+			case PESSIMISTIC_WRITE: {
+				return LockMode.PESSIMISTIC_WRITE;
+			}
+			case PESSIMISTIC_FORCE_INCREMENT: {
+				return LockMode.PESSIMISTIC_FORCE_INCREMENT;
+			}
+			case NONE: {
+				return LockMode.NONE;
+			}
+			default: {
+				throw new AssertionFailure( "Unknown LockModeType: " + lockMode );
+			}
+		}
+	}
+
+	public static LockMode interpretLockMode(Object value) {
+		if ( value == null ) {
+			return LockMode.NONE;
+		}
+		if ( LockMode.class.isInstance( value ) ) {
+			return (LockMode) value;
+		}
+		else if ( LockModeType.class.isInstance( value ) ) {
+			return getLockMode( (LockModeType) value );
+		}
+		else if ( String.class.isInstance( value ) ) {
+			// first try LockMode name
+			LockMode lockMode = LockMode.parse( (String) value );
+			if ( lockMode == null ) {
+				try {
+					lockMode = getLockMode( LockModeType.valueOf( (String) value ) );
+				}
+				catch ( Exception ignore ) {
+				}
+			}
+			if ( lockMode != null ) {
+				return lockMode;
+			}
+		}
+
+		throw new IllegalArgumentException( "Unknown lock mode source : " + value );
+	}
+
+}

Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/dialect/unit/lockhint/AbstractLockHintTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/dialect/unit/lockhint/AbstractLockHintTest.java	2010-01-31 21:50:23 UTC (rev 18674)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/dialect/unit/lockhint/AbstractLockHintTest.java	2010-02-01 19:42:16 UTC (rev 18675)
@@ -56,7 +56,7 @@
 
 		public void verify() {
 			LockOptions lockOptions = new LockOptions(LockMode.UPGRADE);
-			lockOptions.setAliasLockMode(LockMode.UPGRADE,  aliasToLock);
+			lockOptions.setAliasSpecificLockMode( aliasToLock, LockMode.UPGRADE );
 			String actualProcessedSql = dialect.applyLocksToSql( rawSql, lockOptions, Collections.EMPTY_MAP );
 			assertEquals( expectedProcessedSql, actualProcessedSql );
 		}



More information about the hibernate-commits mailing list