[hibernate-commits] Hibernate SVN: r18243 - in core/trunk: core/src/main/java/org/hibernate/dialect and 13 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Wed Dec 16 13:23:32 EST 2009


Author: smarlow at redhat.com
Date: 2009-12-16 13:23:31 -0500 (Wed, 16 Dec 2009)
New Revision: 18243

Modified:
   core/trunk/core/src/main/java/org/hibernate/LockOptions.java
   core/trunk/core/src/main/java/org/hibernate/Query.java
   core/trunk/core/src/main/java/org/hibernate/dialect/AbstractTransactSQLDialect.java
   core/trunk/core/src/main/java/org/hibernate/dialect/Dialect.java
   core/trunk/core/src/main/java/org/hibernate/engine/QueryParameters.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/impl/SQLQueryImpl.java
   core/trunk/core/src/main/java/org/hibernate/loader/JoinWalker.java
   core/trunk/core/src/main/java/org/hibernate/loader/Loader.java
   core/trunk/core/src/main/java/org/hibernate/loader/OuterJoinLoader.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/custom/CustomLoader.java
   core/trunk/core/src/main/java/org/hibernate/loader/hql/QueryLoader.java
   core/trunk/core/src/main/java/org/hibernate/sql/ForUpdateFragment.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/HibernateEntityManagerImplementor.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/QueryImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/TransactionImpl.java
   core/trunk/envers/src/main/java/org/hibernate/envers/query/impl/AbstractAuditQuery.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/dialect/unit/lockhint/AbstractLockHintTest.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/legacy/FooBarTest.java
Log:
HHH-4546 JPA-2 locking.  LockOptions can include per table alias LockMode

Modified: core/trunk/core/src/main/java/org/hibernate/LockOptions.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/LockOptions.java	2009-12-16 18:23:19 UTC (rev 18242)
+++ core/trunk/core/src/main/java/org/hibernate/LockOptions.java	2009-12-16 18:23:31 UTC (rev 18243)
@@ -23,6 +23,11 @@
  */
 package org.hibernate;
 
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Iterator;
+
+
 /**
  * Contains locking details (LockMode, Timeout and Scope).
  * 
@@ -59,6 +64,8 @@
 	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() {
 
 	}
@@ -88,6 +95,49 @@
 	}
 
 	/**
+	 * Specify the LockMode to be used for the specified 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.
+	 * @return this LockRequest instance for operation chaining.
+	 */
+	public LockOptions setAliasLockMode(LockMode lockMode, String alias) {
+		lockModesByName.put(alias, lockMode);
+		return this;
+	}
+
+	/**
+	 * Get the lock mode for the specified alias.
+	 *
+	 * @param alias used to reference the LockMode.
+	 * @return the lock mode.
+	 */
+	public LockMode getAliasLockMode(String alias) {
+		return (LockMode)lockModesByName.get(alias);
+	}
+
+	/**
+	 * Get the number of aliases that have LockModes specified
+	 *
+	 * @return the number of aliases
+	 */
+	public int getAliasLockCount() {
+		return lockModesByName.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();
+	}
+
+	/**
 	 * Get the timeout setting.
 	 *
 	 * @return timeout in milliseconds, -1 for indefinite wait and 0 for no wait.
@@ -128,8 +178,10 @@
 		return this;
 	}
 
+
 	/**
-	 * Copy From to Dest
+	 * Shallow copy From to Dest
+	 *
 	 * @param from is copied from
 	 * @param dest is copied to
 	 * @return dest
@@ -138,6 +190,7 @@
 		dest.setLockMode(from.getLockMode());
 		dest.setScope(from.getScope());
 		dest.setTimeOut(from.getTimeOut());
+		dest.lockModesByName = new HashMap(from.lockModesByName);
 		return dest;
 	}
 

Modified: core/trunk/core/src/main/java/org/hibernate/Query.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/Query.java	2009-12-16 18:23:19 UTC (rev 18242)
+++ core/trunk/core/src/main/java/org/hibernate/Query.java	2009-12-16 18:23:31 UTC (rev 18243)
@@ -209,15 +209,13 @@
 	/**
 	 * Set the lock options for the objects idententified by the
 	 * given alias that appears in the <tt>FROM</tt> clause.
-	 * @param alias a query alias, or <tt>this</tt> for a collection filter
 	 */
-	public Query setLockOptions(String alias, LockOptions lockOptions);
+	public Query setLockOptions(LockOptions lockOptions);
 
 	/**
 	 * Set the lockmode for the objects idententified by the
 	 * given alias that appears in the <tt>FROM</tt> clause.
 	 * @param alias a query alias, or <tt>this</tt> for a collection filter
-	 * @deprecated Instead use setLockOptions
 	 */
 	public Query setLockMode(String alias, LockMode lockMode);
 

Modified: core/trunk/core/src/main/java/org/hibernate/dialect/AbstractTransactSQLDialect.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/AbstractTransactSQLDialect.java	2009-12-16 18:23:19 UTC (rev 18242)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/AbstractTransactSQLDialect.java	2009-12-16 18:23:31 UTC (rev 18243)
@@ -169,14 +169,13 @@
 		}
 	}
 
-	public String applyLocksToSql(String sql, Map aliasedLockOptions, Map keyColumnNames) {
-		Iterator itr = aliasedLockOptions.entrySet().iterator();
+	public String applyLocksToSql(String sql, LockOptions aliasedLockOptions, Map keyColumnNames) {
+		Iterator itr = aliasedLockOptions.getAliasLockIterator();
 		StringBuffer buffer = new StringBuffer( sql );
 		int correction = 0;
 		while ( itr.hasNext() ) {
 			final Map.Entry entry = ( Map.Entry ) itr.next();
-			final LockOptions lockOption = ( LockOptions ) entry.getValue();
-			final LockMode lockMode = lockOption.getLockMode();
+			final LockMode lockMode = ( LockMode ) entry.getValue();
 			if ( lockMode.greaterThan( LockMode.READ ) ) {
 				final String alias = ( String ) entry.getKey();
 				int start = -1, end = -1;

Modified: core/trunk/core/src/main/java/org/hibernate/dialect/Dialect.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/Dialect.java	2009-12-16 18:23:19 UTC (rev 18242)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/Dialect.java	2009-12-16 18:23:31 UTC (rev 18243)
@@ -1138,11 +1138,11 @@
 	 * <tt>SELECT FOR UPDATE</tt> to achieve this in their own fashion.
 	 *
 	 * @param sql the SQL string to modify
-	 * @param aliasedLockOptions a map of lock options indexed by aliased table names.
+	 * @param aliasedLockOptions lock options indexed by aliased table names.
 	 * @param keyColumnNames a map of key columns indexed by aliased table names.
 	 * @return the modified SQL string.
 	 */
-	public String applyLocksToSql(String sql, Map aliasedLockOptions, Map keyColumnNames) {
+	public String applyLocksToSql(String sql, LockOptions aliasedLockOptions, Map keyColumnNames) {
 		return sql + new ForUpdateFragment( this, aliasedLockOptions, keyColumnNames ).toFragmentString();
 	}
 

Modified: core/trunk/core/src/main/java/org/hibernate/engine/QueryParameters.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/engine/QueryParameters.java	2009-12-16 18:23:19 UTC (rev 18242)
+++ core/trunk/core/src/main/java/org/hibernate/engine/QueryParameters.java	2009-12-16 18:23:31 UTC (rev 18243)
@@ -1,7 +1,7 @@
 /*
  * Hibernate, Relational Persistence for Idiomatic Java
  *
- * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * Copyright (c) 2009, Red Hat Middleware LLC 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.
@@ -38,6 +38,7 @@
 import org.hibernate.HibernateException;
 import org.hibernate.QueryException;
 import org.hibernate.ScrollMode;
+import org.hibernate.LockOptions;
 import org.hibernate.impl.FilterImpl;
 import org.hibernate.dialect.Dialect;
 import org.hibernate.hql.classic.ParserHelper;
@@ -55,7 +56,7 @@
 	private Type[] positionalParameterTypes;
 	private Object[] positionalParameterValues;
 	private Map namedParameters;
-	private Map lockOptions;
+	private LockOptions lockOptions;
 	private RowSelection rowSelection;
 	private boolean cacheable;
 	private String cacheRegion;
@@ -133,7 +134,7 @@
 	public QueryParameters(
 			final Type[] positionalParameterTypes,
 			final Object[] positionalParameterValues,
-			final Map lockOptions,
+			final LockOptions lockOptions,
 			final RowSelection rowSelection,
 			final boolean cacheable,
 			final String cacheRegion,
@@ -161,7 +162,7 @@
 			final Type[] positionalParameterTypes,
 			final Object[] positionalParameterValues,
 			final Map namedParameters,
-			final Map lockOptions,
+			final LockOptions lockOptions,
 			final RowSelection rowSelection,
 			final boolean readOnly,
 			final boolean cacheable,
@@ -188,7 +189,7 @@
 			final Type[] positionalParameterTypes,
 			final Object[] positionalParameterValues,
 			final Map namedParameters,
-			final Map lockOptions,
+			final LockOptions lockOptions,
 			final RowSelection rowSelection,
 			final boolean readOnly,
 			final boolean cacheable,
@@ -258,14 +259,10 @@
 		rowSelection = selection;
 	}
 
-	public Map getLockOptions() {
+	public LockOptions getLockOptions() {
 		return lockOptions;
 	}
 
-	public void setLockOptions(Map map) {
-		lockOptions = map;
-	}
-
 	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/hql/classic/QueryTranslatorImpl.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/hql/classic/QueryTranslatorImpl.java	2009-12-16 18:23:19 UTC (rev 18242)
+++ core/trunk/core/src/main/java/org/hibernate/hql/classic/QueryTranslatorImpl.java	2009-12-16 18:23:31 UTC (rev 18243)
@@ -1037,40 +1037,50 @@
 		holderClass = clazz;
 	}
 
-	protected LockOptions[] getLockOptions(Map lockOptions) {
+	protected LockMode[] getLockModes(LockOptions lockOptions) {
+
 		// unfortunately this stuff can't be cached because
 		// it is per-invocation, not constant for the
 		// QueryTranslator instance
 		HashMap nameLockOptions = new HashMap();
-		if ( lockOptions != null ) {
-			Iterator iter = lockOptions.entrySet().iterator();
+		if ( lockOptions == null) {
+			lockOptions = LockOptions.NONE;
+		}
+
+		if ( lockOptions.getAliasLockCount() > 0 ) {
+			Iterator iter = lockOptions.getAliasLockIterator();
 			while ( iter.hasNext() ) {
 				Map.Entry me = ( Map.Entry ) iter.next();
 				nameLockOptions.put( getAliasName( ( String ) me.getKey() ),
 						me.getValue() );
 			}
 		}
-		LockOptions[] lockOptionsArray = new LockOptions[names.length];
+		LockMode[] lockModesArray = new LockMode[names.length];
 		for ( int i = 0; i < names.length; i++ ) {
-			LockOptions lm = ( LockOptions ) nameLockOptions.get( names[i] );
-			if ( lm == null ) lm = LockOptions.NONE;
-			lockOptionsArray[i] = lm;
+			LockMode lm = ( LockMode ) nameLockOptions.get( names[i] );
+			//if ( lm == null ) lm = LockOptions.NONE;
+			if ( lm == null ) lm = lockOptions.getLockMode();
+			lockModesArray[i] = lm;
 		}
-		return lockOptionsArray;
+		return lockModesArray;
 	}
 
-	protected String applyLocks(String sql, Map lockOptions, Dialect dialect) throws QueryException {
+	protected String applyLocks(String sql, LockOptions lockOptions, Dialect dialect) throws QueryException {
 		// can't cache this stuff either (per-invocation)
 		final String result;
-		if ( lockOptions == null || lockOptions.size() == 0 ) {
-			result = sql;
+		if ( lockOptions == null ||
+			( lockOptions.getLockMode() == LockMode.NONE && lockOptions.getAliasLockCount() == 0 ) ) {
+			return sql;
 		}
 		else {
-			Map aliasedLockOptions = new HashMap();
-			Iterator iter = lockOptions.entrySet().iterator();
+			LockOptions locks = new LockOptions();
+			locks.setLockMode(lockOptions.getLockMode());
+			locks.setTimeOut(lockOptions.getTimeOut());
+			locks.setScope(lockOptions.getScope());
+			Iterator iter = lockOptions.getAliasLockIterator();
 			while ( iter.hasNext() ) {
 				Map.Entry me = ( Map.Entry ) iter.next();
-				aliasedLockOptions.put( getAliasName( ( String ) me.getKey() ), me.getValue() );
+				locks.setAliasLockMode( (LockMode) me.getValue(),  getAliasName( ( String ) me.getKey() ) );
 			}
 			Map keyColumnNames = null;
 			if ( dialect.forUpdateOfColumns() ) {
@@ -1079,7 +1089,7 @@
 					keyColumnNames.put( names[i], persisters[i].getIdentifierColumnNames() );
 				}
 			}
-			result = dialect.applyLocksToSql( sql, aliasedLockOptions, keyColumnNames );
+			result = dialect.applyLocksToSql( sql, locks, keyColumnNames );
 		}
 		logQuery( queryString, result );
 		return result;

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	2009-12-16 18:23:19 UTC (rev 18242)
+++ core/trunk/core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java	2009-12-16 18:23:31 UTC (rev 18243)
@@ -30,7 +30,6 @@
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.util.Properties;
-import java.util.HashMap;
 import java.util.Collections;
 import java.util.Map;
 import java.io.Serializable;
@@ -47,6 +46,7 @@
 import org.hibernate.HibernateException;
 import org.hibernate.MappingException;
 import org.hibernate.LockOptions;
+import org.hibernate.LockMode;
 import org.hibernate.cfg.ObjectNameNormalizer;
 import org.hibernate.jdbc.util.FormatStyle;
 import org.hibernate.mapping.Table;
@@ -428,10 +428,10 @@
 		String query = "select " + StringHelper.qualify( alias, valueColumnName ) +
 				" from " + tableName + ' ' + alias +
 				" where " + StringHelper.qualify( alias, segmentColumnName ) + "=?";
-		HashMap lockMap = new HashMap();
-		lockMap.put( alias,  LockOptions.UPGRADE );
+		LockOptions lockOptions = new LockOptions(LockMode.UPGRADE);
+		lockOptions.setAliasLockMode(LockMode.UPGRADE, alias);
 		Map updateTargetColumnsMap = Collections.singletonMap( alias, new String[] { valueColumnName } );
-		return dialect.applyLocksToSql( query, lockMap, updateTargetColumnsMap );
+		return dialect.applyLocksToSql( query, lockOptions, updateTargetColumnsMap );
 	}
 
 	protected String buildUpdateQuery() {

Modified: core/trunk/core/src/main/java/org/hibernate/impl/AbstractQueryImpl.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/impl/AbstractQueryImpl.java	2009-12-16 18:23:19 UTC (rev 18242)
+++ core/trunk/core/src/main/java/org/hibernate/impl/AbstractQueryImpl.java	2009-12-16 18:23:31 UTC (rev 18243)
@@ -49,6 +49,7 @@
 import org.hibernate.PropertyNotFoundException;
 import org.hibernate.Query;
 import org.hibernate.QueryException;
+import org.hibernate.LockOptions;
 import org.hibernate.engine.QueryParameters;
 import org.hibernate.engine.RowSelection;
 import org.hibernate.engine.SessionImplementor;
@@ -227,7 +228,7 @@
 		return session;
 	}
 
-	protected abstract Map getLockOptions();
+	protected 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	2009-12-16 18:23:19 UTC (rev 18242)
+++ core/trunk/core/src/main/java/org/hibernate/impl/QueryImpl.java	2009-12-16 18:23:31 UTC (rev 18243)
@@ -24,7 +24,6 @@
  */
 package org.hibernate.impl;
 
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -48,7 +47,7 @@
  */
 public class QueryImpl extends AbstractQueryImpl {
 
-	private Map lockOptions = new HashMap(2);
+	private LockOptions lockOptions = new LockOptions();
 
 	public QueryImpl(
 			String queryString,
@@ -126,15 +125,18 @@
 	}
 
 	public Query setLockMode(String alias, LockMode lockMode) {
-		return setLockOptions( alias, new LockOptions(lockMode) );
+		lockOptions.setAliasLockMode(lockMode, alias);
+		return this;
 	}
 	
-	public Query setLockOptions(String alias, LockOptions lockOption) {
-		lockOptions.put(alias, lockOption);
+	public Query setLockOptions(LockOptions lockOption) {
+		this.lockOptions.setLockMode(lockOption.getLockMode());
+		this.lockOptions.setScope(lockOption.getScope());
+		this.lockOptions.setTimeOut(lockOptions.getTimeOut());
 		return this;
 	}
 
-	protected Map getLockOptions() {
+	protected LockOptions getLockOptions() {
 		return lockOptions;
 	}
 

Modified: core/trunk/core/src/main/java/org/hibernate/impl/SQLQueryImpl.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/impl/SQLQueryImpl.java	2009-12-16 18:23:19 UTC (rev 18242)
+++ core/trunk/core/src/main/java/org/hibernate/impl/SQLQueryImpl.java	2009-12-16 18:23:31 UTC (rev 18243)
@@ -254,13 +254,13 @@
 		throw new UnsupportedOperationException("cannot set the lock mode for a native SQL query");
 	}
 
-	public Query setLockOptions(String alias, LockOptions lockOptions) {
+	public Query setLockOptions(LockOptions lockOptions) {
 		throw new UnsupportedOperationException("cannot set lock options for a native SQL query");
 	}
 
-	protected Map getLockOptions() {
+	protected LockOptions getLockOptions() {
 		//we never need to apply locks to the SQL
-		return CollectionHelper.EMPTY_MAP;
+		return null;
 	}
 
 	public SQLQuery addScalar(String columnAlias, Type type) {

Modified: core/trunk/core/src/main/java/org/hibernate/loader/JoinWalker.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/loader/JoinWalker.java	2009-12-16 18:23:19 UTC (rev 18242)
+++ core/trunk/core/src/main/java/org/hibernate/loader/JoinWalker.java	2009-12-16 18:23:31 UTC (rev 18243)
@@ -82,7 +82,8 @@
 	protected CollectionPersister[] collectionPersisters;
 	protected int[] collectionOwners;
 	protected String[] aliases;
-	protected LockOptions[] lockOptionsArray;
+	protected LockOptions lockOptions;
+	protected LockMode[] lockModeArray;
 	protected String sql;
 
 	protected JoinWalker(
@@ -101,12 +102,12 @@
 		this.collectionSuffixes = collectionSuffixes;
 	}
 
-	public LockOptions[] getLockModeOptions() {
-		return lockOptionsArray;
+	public LockOptions getLockModeOptions() {
+		return lockOptions;
 	}
 
-	public void setLockOptionsArray(LockOptions[] lockOptionsArray) {
-		this.lockOptionsArray = lockOptionsArray;
+	public LockMode[] getLockModeArray() {
+		return lockModeArray;
 	}
 
 	public String[] getSuffixes() {
@@ -993,12 +994,14 @@
 		collectionPersisters = collections==0 ? null : new CollectionPersister[collections];
 		collectionSuffixes = BasicLoader.generateSuffixes( joins + 1, collections );
 
+		this.lockOptions = lockOptions;
+
 		persisters = new Loadable[joins];
 		aliases = new String[joins];
 		owners = new int[joins];
 		ownerAssociationTypes = new EntityType[joins];
-		lockOptionsArray = ArrayHelper.fillArray(lockOptions, joins);
-		
+		lockModeArray = ArrayHelper.fillArray(lockOptions.getLockMode(), joins);
+
 		int i=0;
 		int j=0;
 		Iterator iter = associations.iterator();

Modified: core/trunk/core/src/main/java/org/hibernate/loader/Loader.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/loader/Loader.java	2009-12-16 18:23:19 UTC (rev 18242)
+++ core/trunk/core/src/main/java/org/hibernate/loader/Loader.java	2009-12-16 18:23:31 UTC (rev 18243)
@@ -178,14 +178,15 @@
 	 *
 	 * @param lockOptions a collection of lock options specified dynamically via the Query interface
 	 */
-	protected abstract LockOptions[] getLockOptions(Map lockOptions);
+	//protected abstract LockOptions[] getLockOptions(Map lockOptions);
+	protected abstract LockMode[] getLockModes(LockOptions lockOptions);
 
 	/**
 	 * Append <tt>FOR UPDATE OF</tt> clause, if necessary. This
 	 * empty superclass implementation merely returns its first
 	 * argument.
 	 */
-	protected String applyLocks(String sql, Map lockOptions, Dialect dialect) throws HibernateException {
+	protected String applyLocks(String sql, LockOptions lockOptions, Dialect dialect) throws HibernateException {
 		return sql;
 	}
 
@@ -214,34 +215,13 @@
 		return null;
 	}
 
-	private Map buildLockMap(Map locks) {
-		Map result = locks;
-		if ( result == null ) {
-			LockOptions[] lockArray = getLockOptions(result);
-			String[] aliases = getAliases();
-			if (aliases != null &&
-				lockArray != null &&
-				lockArray.length > 0 &&
-				lockArray.length == aliases.length &&
-				lockArray[0].getLockMode() != LockMode.NONE ) {
-				result = new HashMap();
-				for ( int looper = 0; looper < lockArray.length; looper++ ) {
-					result.put(aliases[looper], lockArray[looper]);
-				}
-			}
-		}
-
-		return result;
-	}
 	/**
 	 * Modify the SQL, adding lock hints and comments, if necessary
 	 */
 	protected String preprocessSQL(String sql, QueryParameters parameters, Dialect dialect)
 			throws HibernateException {
 
-		Map locks = buildLockMap(parameters.getLockOptions());
-
-		sql = applyLocks( sql, locks, dialect );
+		sql = applyLocks( sql, parameters.getLockOptions(), dialect );
 		
 		return getFactory().getSettings().isCommentsEnabled() ?
 				prependComment( sql, parameters ) : sql;
@@ -312,7 +292,7 @@
 			        resultSet,
 					session,
 					queryParameters,
-					getLockOptions( queryParameters.getLockOptions() ),
+					getLockModes( queryParameters.getLockOptions() ),
 					null,
 					hydratedObjects,
 					new EntityKey[entitySpan],
@@ -358,7 +338,7 @@
 						resultSet,
 						session,
 						queryParameters,
-						getLockOptions( queryParameters.getLockOptions() ),
+						getLockModes( queryParameters.getLockOptions() ),
 						null,
 						hydratedObjects,
 						loadedKeys,
@@ -595,7 +575,7 @@
 	        final ResultSet resultSet,
 	        final SessionImplementor session,
 	        final QueryParameters queryParameters,
-	        final LockOptions[] lockOptionsArray,
+	        final LockMode[] lockModesArray,
 	        final EntityKey optionalObjectKey,
 	        final List hydratedObjects,
 	        final EntityKey[] keys,
@@ -626,7 +606,7 @@
 				keys,
 				queryParameters.getOptionalObject(),
 				optionalObjectKey,
-				lockOptionsArray,
+				lockModesArray,
 				hydratedObjects,
 				session
 		);
@@ -723,7 +703,7 @@
 // that I could do the control breaking at the means to know when to stop
 
 		final EntityKey optionalObjectKey = getOptionalObjectKey( queryParameters, session );
-		final LockOptions[] lockOptionsArray = getLockOptions( queryParameters.getLockOptions() );
+		final LockMode[] lockModesArray = getLockModes( queryParameters.getLockOptions() );
 		final boolean createSubselects = isSubselectLoadingEnabled();
 		final List subselectResultKeys = createSubselects ? new ArrayList() : null;
 		final List results = new ArrayList();
@@ -745,7 +725,7 @@
 						rs,
 						session,
 						queryParameters,
-						lockOptionsArray,
+						lockModesArray,
 						optionalObjectKey,
 						hydratedObjects,
 						keys,
@@ -1205,7 +1185,7 @@
 	        final EntityKey[] keys,
 	        final Object optionalObject,
 	        final EntityKey optionalObjectKey,
-	        final LockOptions[] lockOptions,
+	        final LockMode[] lockModes,
 	        final List hydratedObjects,
 	        final SessionImplementor session) 
 	throws HibernateException, SQLException {
@@ -1242,7 +1222,7 @@
 							persisters[i],
 							key,
 							object,
-							lockOptions[i],
+							lockModes[i],
 							session 
 						);
 				}
@@ -1253,7 +1233,7 @@
 							persisters[i],
 							descriptors[i].getRowIdAlias(),
 							key,
-							lockOptions[i],
+							lockModes[i],
 							optionalObjectKey,
 							optionalObject,
 							hydratedObjects,
@@ -1279,10 +1259,9 @@
 	        final Loadable persister,
 	        final EntityKey key,
 	        final Object object,
-	        final LockOptions lockOptions,
+	        final LockMode lockMode,
 	        final SessionImplementor session) 
 	throws HibernateException, SQLException {
-		LockMode lockMode = (lockOptions == null) ? null : lockOptions.getLockMode();
 		if ( !persister.isInstance( object, session.getEntityMode() ) ) {
 			throw new WrongClassException( 
 					"loaded object was of wrong class " + object.getClass(), 
@@ -1318,14 +1297,13 @@
 	        final Loadable persister,
 	        final String rowIdAlias,
 	        final EntityKey key,
-	        final LockOptions lockOptions,
+	        final LockMode lockMode,
 	        final EntityKey optionalObjectKey,
 	        final Object optionalObject,
 	        final List hydratedObjects,
 	        final SessionImplementor session) 
 	throws HibernateException, SQLException {
-		LockMode lockMode = (lockOptions == null) ? null : lockOptions.getLockMode();
-		final String instanceClass = getInstanceClass( 
+		final String instanceClass = getInstanceClass(
 				rs, 
 				i, 
 				persister, 

Modified: core/trunk/core/src/main/java/org/hibernate/loader/OuterJoinLoader.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/loader/OuterJoinLoader.java	2009-12-16 18:23:19 UTC (rev 18242)
+++ core/trunk/core/src/main/java/org/hibernate/loader/OuterJoinLoader.java	2009-12-16 18:23:31 UTC (rev 18243)
@@ -27,6 +27,7 @@
 import java.util.Map;
 
 import org.hibernate.LockOptions;
+import org.hibernate.LockMode;
 import org.hibernate.dialect.Dialect;
 import org.hibernate.engine.SessionFactoryImplementor;
 import org.hibernate.engine.LoadQueryInfluencers;
@@ -48,7 +49,8 @@
 	protected CollectionPersister[] collectionPersisters;
 	protected int[] collectionOwners;
 	protected String[] aliases;
-	protected LockOptions[] lockOptionsArray;
+	private LockOptions lockOptions;
+	protected LockMode[] lockModeArray;
 	protected int[] owners;
 	protected EntityType[] ownerAssociationTypes;
 	protected String sql;
@@ -92,10 +94,14 @@
 		return ownerAssociationTypes;
 	}
 
-	protected LockOptions[] getLockOptions(Map lockModes) {
-		return lockOptionsArray;
+	protected LockMode[] getLockModes(LockOptions lockOptions) {
+		return lockModeArray;
 	}
 
+	protected LockOptions getLockOptions() {
+		return lockOptions;
+	}
+
 	public LoadQueryInfluencers getLoadQueryInfluencers() {
 		return loadQueryInfluencers;
 	}
@@ -116,7 +122,8 @@
 		persisters = walker.getPersisters();
 		collectionPersisters = walker.getCollectionPersisters();
 		ownerAssociationTypes = walker.getOwnerAssociationTypes();
-		lockOptionsArray = walker.getLockModeOptions();
+		lockOptions = walker.getLockModeOptions();
+		lockModeArray = walker.getLockModeArray();
 		suffixes = walker.getSuffixes();
 		collectionSuffixes = walker.getCollectionSuffixes();
 		owners = walker.getOwners();

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	2009-12-16 18:23:19 UTC (rev 18242)
+++ core/trunk/core/src/main/java/org/hibernate/loader/criteria/CriteriaLoader.java	2009-12-16 18:23:31 UTC (rev 18243)
@@ -1,7 +1,7 @@
 /*
  * Hibernate, Relational Persistence for Idiomatic Java
  *
- * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * Copyright (c) 2009, Red Hat Middleware LLC 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.
@@ -144,38 +144,42 @@
 		return querySpaces;
 	}
 
-	protected String applyLocks(String sqlSelectString, Map lockOptions, Dialect dialect) throws QueryException {
-		if ( lockOptions == null || lockOptions.isEmpty() ) {
+	protected String applyLocks(String sqlSelectString, LockOptions lockOptions, Dialect dialect) throws QueryException {
+		if ( lockOptions == null ||
+			( lockOptions.getLockMode() == LockMode.NONE && lockOptions.getAliasLockCount() == 0 ) ) {
 			return sqlSelectString;
 		}
 
-		final Map aliasedLockOptions = new HashMap();
+		final LockOptions locks = new LockOptions(lockOptions.getLockMode());
+		locks.setScope( lockOptions.getScope());
+		locks.setTimeOut( lockOptions.getTimeOut());
+
 		final Map keyColumnNames = dialect.forUpdateOfColumns() ? new HashMap() : null;
 		final String[] drivingSqlAliases = getAliases();
 		for ( int i = 0; i < drivingSqlAliases.length; i++ ) {
-			final LockOptions lockOption = ( LockOptions ) lockOptions.get( drivingSqlAliases[i] );
-			if ( lockOption != null ) {
+			final LockMode lockMode = lockOptions.getAliasLockMode( drivingSqlAliases[i] );
+			if ( lockMode != null ) {
 				final Lockable drivingPersister = ( Lockable ) getEntityPersisters()[i];
 				final String rootSqlAlias = drivingPersister.getRootTableAlias( drivingSqlAliases[i] );
-				aliasedLockOptions.put( rootSqlAlias, lockOption );
+				locks.setAliasLockMode(lockMode, rootSqlAlias);
 				if ( keyColumnNames != null ) {
 					keyColumnNames.put( rootSqlAlias, drivingPersister.getRootTableIdentifierColumnNames() );
 				}
 			}
 		}
-		return dialect.applyLocksToSql( sqlSelectString, aliasedLockOptions, keyColumnNames );
+		return dialect.applyLocksToSql( sqlSelectString, locks, keyColumnNames );
 	}
 
-	protected LockOptions[] getLockOptions(Map lockOptions) {
+	protected LockMode[] getLockModes(LockOptions lockOptions) {
 		final String[] entityAliases = getAliases();
 		if ( entityAliases == null ) {
 			return null;
 		}
 		final int size = entityAliases.length;
-		LockOptions[] lockModesArray = new LockOptions[size];
+		LockMode[] lockModesArray = new LockMode[size];
 		for ( int i=0; i<size; i++ ) {
-			LockOptions lockOption = (LockOptions) lockOptions.get( entityAliases[i] );
-			lockModesArray[i] = lockOption==null ? LockOptions.NONE : lockOption;
+			LockMode lockMode = lockOptions.getAliasLockMode( 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	2009-12-16 18:23:19 UTC (rev 18242)
+++ core/trunk/core/src/main/java/org/hibernate/loader/criteria/CriteriaQueryTranslator.java	2009-12-16 18:23:31 UTC (rev 18243)
@@ -41,6 +41,7 @@
 import org.hibernate.LockMode;
 import org.hibernate.MappingException;
 import org.hibernate.QueryException;
+import org.hibernate.LockOptions;
 import org.hibernate.hql.ast.util.SessionFactoryHelper;
 import org.hibernate.criterion.CriteriaQuery;
 import org.hibernate.criterion.Criterion;
@@ -272,18 +273,18 @@
 	}
 
 	public QueryParameters getQueryParameters() {
+		LockOptions lockOptions = new LockOptions();
 		RowSelection selection = new RowSelection();
 		selection.setFirstRow( rootCriteria.getFirstResult() );
 		selection.setMaxRows( rootCriteria.getMaxResults() );
 		selection.setTimeout( rootCriteria.getTimeout() );
 		selection.setFetchSize( rootCriteria.getFetchSize() );
 
-		Map lockModes = new HashMap();
 		Iterator iter = rootCriteria.getLockModes().entrySet().iterator();
 		while ( iter.hasNext() ) {
 			Map.Entry me = ( Map.Entry ) iter.next();
 			final Criteria subcriteria = getAliasedCriteria( ( String ) me.getKey() );
-			lockModes.put( getSQLAlias( subcriteria ), me.getValue() );
+			lockOptions.setAliasLockMode( (LockMode)me.getValue(), getSQLAlias( subcriteria ) );
 		}
 		List values = new ArrayList();
 		List types = new ArrayList();
@@ -292,7 +293,7 @@
 			CriteriaImpl.Subcriteria subcriteria = ( CriteriaImpl.Subcriteria ) iter.next();
 			LockMode lm = subcriteria.getLockMode();
 			if ( lm != null ) {
-				lockModes.put( getSQLAlias( subcriteria ), lm );
+				lockOptions.setAliasLockMode( lm, getSQLAlias( subcriteria ) );
 			}
 			if ( subcriteria.getWithClause() != null )
 			{
@@ -322,7 +323,7 @@
 		return new QueryParameters(
 				typeArray,
 		        valueArray,
-		        lockModes,
+		        lockOptions,
 		        selection,
 		        rootCriteria.getCacheable(),
 		        rootCriteria.getCacheRegion(),

Modified: core/trunk/core/src/main/java/org/hibernate/loader/custom/CustomLoader.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/loader/custom/CustomLoader.java	2009-12-16 18:23:19 UTC (rev 18242)
+++ core/trunk/core/src/main/java/org/hibernate/loader/custom/CustomLoader.java	2009-12-16 18:23:31 UTC (rev 18243)
@@ -79,7 +79,8 @@
 	private final int[] collectionOwners;
 	private final CollectionAliases[] collectionAliases;
 
-	private final LockOptions[] lockOptions;
+	private final LockMode[] lockModes;
+
 //	private final String[] sqlAliases;
 //	private final String[] sqlAliasSuffixes;
 	private final ResultRowProcessor rowProcessor;
@@ -107,7 +108,7 @@
 		List collectionOwners = new ArrayList();
 		List collectionAliases = new ArrayList();
 
-		List lockOptions = new ArrayList();
+		List lockModes = new ArrayList();
 		List resultColumnProcessors = new ArrayList();
 		List nonScalarReturnList = new ArrayList();
 		List resultTypes = new ArrayList();
@@ -134,8 +135,7 @@
 				RootReturn rootRtn = ( RootReturn ) rtn;
 				Queryable persister = ( Queryable ) factory.getEntityPersister( rootRtn.getEntityName() );
 				entityPersisters.add( persister );
-				// TODO: get lock options from rootRTN
-				lockOptions.add( new LockOptions(rootRtn.getLockMode()) );
+				lockModes.add( (rootRtn.getLockMode()) );
 				resultColumnProcessors.add( new NonScalarResultColumnProcessor( returnableCounter++ ) );
 				nonScalarReturnList.add( rtn );
 				entityOwners.add( new Integer( -1 ) );
@@ -149,8 +149,7 @@
 				String role = collRtn.getOwnerEntityName() + "." + collRtn.getOwnerProperty();
 				QueryableCollection persister = ( QueryableCollection ) factory.getCollectionPersister( role );
 				collectionPersisters.add( persister );
-				// TODO: get lock options from collRtn
-				lockOptions.add( new LockOptions(collRtn.getLockMode()) );
+				lockModes.add( collRtn.getLockMode() );
 				resultColumnProcessors.add( new NonScalarResultColumnProcessor( returnableCounter++ ) );
 				nonScalarReturnList.add( rtn );
 				collectionOwners.add( new Integer( -1 ) );
@@ -172,8 +171,7 @@
 				NonScalarReturn ownerDescriptor = fetchRtn.getOwner();
 				int ownerIndex = nonScalarReturnList.indexOf( ownerDescriptor );
 				entityOwners.add( new Integer( ownerIndex ) );
-				// TODO:  get lock options from fetchRtn
-				lockOptions.add( new LockOptions(fetchRtn.getLockMode()) );
+				lockModes.add( fetchRtn.getLockMode() );
 				Queryable ownerPersister = determineAppropriateOwnerPersister( ownerDescriptor );
 				EntityType fetchedType = ( EntityType ) ownerPersister.getPropertyType( fetchRtn.getOwnerProperty() );
 				String entityName = fetchedType.getAssociatedEntityName( getFactory() );
@@ -189,8 +187,7 @@
 				NonScalarReturn ownerDescriptor = fetchRtn.getOwner();
 				int ownerIndex = nonScalarReturnList.indexOf( ownerDescriptor );
 				collectionOwners.add( new Integer( ownerIndex ) );
-				// TODO:  get lock options from fetchRtn
-				lockOptions.add( new LockOptions(fetchRtn.getLockMode()) );
+				lockModes.add( fetchRtn.getLockMode() );
 				Queryable ownerPersister = determineAppropriateOwnerPersister( ownerDescriptor );
 				String role = ownerPersister.getEntityName() + '.' + fetchRtn.getOwnerProperty();
 				QueryableCollection persister = ( QueryableCollection ) factory.getCollectionPersister( role );
@@ -233,9 +230,9 @@
 			this.collectionAliases[i] = ( CollectionAliases ) collectionAliases.get( i );
 		}
 
-		this.lockOptions = new LockOptions[ lockOptions.size() ];
-		for ( int i = 0; i < lockOptions.size(); i++ ) {
-			this.lockOptions[i] = ( LockOptions ) lockOptions.get( i );
+		this.lockModes = new LockMode[ lockModes.size() ];
+		for ( int i = 0; i < lockModes.size(); i++ ) {
+			this.lockModes[i] = ( LockMode ) lockModes.get( i );
 		}
 
 		this.resultTypes = ArrayHelper.toTypeArray( resultTypes );
@@ -293,8 +290,8 @@
 		return querySpaces;
 	}
 
-	protected LockOptions[] getLockOptions(Map lockModesMap) {
-		return lockOptions;
+	protected LockMode[] getLockModes(LockOptions lockOptions) {
+		return lockModes;
 	}
 
 	protected Loadable[] getEntityPersisters() {

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	2009-12-16 18:23:19 UTC (rev 18242)
+++ core/trunk/core/src/main/java/org/hibernate/loader/hql/QueryLoader.java	2009-12-16 18:23:31 UTC (rev 18243)
@@ -101,7 +101,7 @@
 	private ResultTransformer implicitResultTransformer;
 	private String[] queryReturnAliases;
 
-	private LockOptions[] defaultLockOptions;
+	private LockMode[] defaultLockModes;
 
 
 	/**
@@ -198,7 +198,7 @@
 		}
 
 		//NONE, because its the requested lock mode, not the actual! 
-		defaultLockOptions = ArrayHelper.fillArray( LockOptions.NONE, size );
+		defaultLockModes = ArrayHelper.fillArray( LockMode.NONE, size );
 	}
 
 	// -- Loader implementation --
@@ -279,40 +279,45 @@
 	/**
 	 * @param lockOptions a collection of lock modes specified dynamically via the Query interface
 	 */
-	protected LockOptions[] getLockOptions(Map lockOptions) {
+	protected LockMode[] getLockModes(LockOptions lockOptions) {
 
-		if ( lockOptions==null || lockOptions.size()==0 ) {
-			return defaultLockOptions;
+		if ( lockOptions == null ||
+			lockOptions.getAliasLockCount() == 0 ) {
+			return defaultLockModes;
 		}
 		else {
 			// unfortunately this stuff can't be cached because
 			// it is per-invocation, not constant for the
 			// QueryTranslator instance
 
-			LockOptions[] lockOptionsArray = new LockOptions[entityAliases.length];
+			LockMode[] lockModesArray = new LockMode[entityAliases.length];
 			for ( int i = 0; i < entityAliases.length; i++ ) {
-				LockOptions options = (LockOptions) lockOptions.get( entityAliases[i] );
-				if ( options == null ) {
+				LockMode lockMode = lockOptions.getAliasLockMode( entityAliases[i] );
+				if ( lockMode == null ) {
 					//NONE, because its the requested lock mode, not the actual! 
-					options = LockOptions.NONE;
+					lockMode = lockOptions.getLockMode();
 				}
-				lockOptionsArray[i] = options;
+				lockModesArray[i] = lockMode;
 			}
-			return lockOptionsArray;
+			return lockModesArray;
 		}
 	}
 
-	protected String applyLocks(String sql, Map lockOptions, Dialect dialect) throws QueryException {
-		if ( lockOptions == null || lockOptions.size() == 0 ) {
+	protected String applyLocks(String sql, LockOptions lockOptions, Dialect dialect) throws QueryException {
+		if ( lockOptions == null ||
+			( lockOptions.getLockMode() == LockMode.NONE && lockOptions.getAliasLockCount() == 0 ) ) {
 			return sql;
 		}
 
 		// 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 Map aliasedLockOptions = new HashMap();
+		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.entrySet().iterator();
+		final Iterator iter = lockOptions.getAliasLockIterator();
 		while ( iter.hasNext() ) {
 			Map.Entry me = ( Map.Entry ) iter.next();
 			final String userAlias = ( String ) me.getKey();
@@ -329,12 +334,12 @@
 			final QueryNode select = ( QueryNode ) queryTranslator.getSqlAST();
 			final Lockable drivingPersister = ( Lockable ) select.getFromClause().getFromElement( userAlias ).getQueryable();
 			final String sqlAlias = drivingPersister.getRootTableAlias( drivingSqlAlias );
-			aliasedLockOptions.put( sqlAlias, me.getValue() );
+			locks.setAliasLockMode( (LockMode)me.getValue(), sqlAlias);
 			if ( keyColumnNames != null ) {
 				keyColumnNames.put( sqlAlias, drivingPersister.getRootTableIdentifierColumnNames() );
 			}
 		}
-		return dialect.applyLocksToSql( sql, aliasedLockOptions, keyColumnNames );
+		return dialect.applyLocksToSql( sql, locks, keyColumnNames );
 	}
 
 	protected boolean upgradeLocks() {

Modified: core/trunk/core/src/main/java/org/hibernate/sql/ForUpdateFragment.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/sql/ForUpdateFragment.java	2009-12-16 18:23:19 UTC (rev 18242)
+++ core/trunk/core/src/main/java/org/hibernate/sql/ForUpdateFragment.java	2009-12-16 18:23:31 UTC (rev 18243)
@@ -26,6 +26,7 @@
 
 import java.util.Iterator;
 import java.util.Map;
+import java.util.HashMap;
 
 import org.hibernate.LockMode;
 import org.hibernate.QueryException;
@@ -40,19 +41,30 @@
 	private final StringBuffer aliases = new StringBuffer();
 	private boolean isNowaitEnabled;
 	private final Dialect dialect;
+	private LockMode lockMode;
+	private LockOptions lockOptions;
 
 	public ForUpdateFragment(Dialect dialect) {
 		this.dialect = dialect;
 	}
 
-	public ForUpdateFragment(Dialect dialect, Map lockOptions, Map keyColumnNames) throws QueryException {
+	public ForUpdateFragment(Dialect dialect, LockOptions lockOptions, Map keyColumnNames) throws QueryException {
 		this( dialect );
 		LockMode upgradeType = null;
-		Iterator iter = lockOptions.entrySet().iterator();
+		Iterator iter = lockOptions.getAliasLockIterator();
+		this.lockOptions =  lockOptions;
+
+		if ( !iter.hasNext()) {  // no tables referenced
+			final LockMode lockMode = lockOptions.getLockMode();
+			if ( LockMode.READ.lessThan( lockMode ) ) {
+				upgradeType = lockMode;
+				this.lockMode = lockMode;
+			}
+		}
+
 		while ( iter.hasNext() ) {
 			final Map.Entry me = ( Map.Entry ) iter.next();
-			final LockOptions lockOption = ( LockOptions ) me.getValue();
-			final LockMode lockMode = lockOption.getLockMode();
+			final LockMode lockMode = ( LockMode ) me.getValue();
 			if ( LockMode.READ.lessThan( lockMode ) ) {
 				final String tableAlias = ( String ) me.getKey();
 				if ( dialect.forUpdateOfColumns() ) {
@@ -89,9 +101,17 @@
 	}
 
 	public String toFragmentString() {
-		if ( aliases.length() == 0 ) {
+
+		if ( aliases.length() == 0) {
+			if ( lockOptions != null ) {
+				return dialect.getForUpdateString(lockOptions);
+			}
+			else if ( lockMode != null ) {
+				return dialect.getForUpdateString(lockMode);
+			}
 			return "";
 		}
+		// TODO:  pass lockmode
 		return isNowaitEnabled ?
 				dialect.getForUpdateNowaitString( aliases.toString() ) :
 				dialect.getForUpdateString( aliases.toString() );

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java	2009-12-16 18:23:19 UTC (rev 18242)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java	2009-12-16 18:23:31 UTC (rev 18243)
@@ -542,7 +542,7 @@
 
 	}
 
-	private LockOptions getLockRequest(LockModeType lockModeType, Map<String, Object> properties) {
+	public LockOptions getLockRequest(LockModeType lockModeType, Map<String, Object> properties) {
 		LockOptions lockOptions = new LockOptions();
 		lockOptions.setLockMode(getLockMode(lockModeType));
 		if ( properties != null ) {
@@ -569,7 +569,7 @@
 		return lockOptions;
 	}
 
-	private LockModeType getLockModeType(LockMode lockMode) {
+	private static LockModeType getLockModeType(LockMode lockMode) {
 		if ( lockMode == LockMode.NONE )
 			return LockModeType.NONE;
 		else if ( lockMode == LockMode.OPTIMISTIC || lockMode == LockMode.READ )
@@ -590,7 +590,7 @@
 	}
 
 
-	private LockMode getLockMode(LockModeType lockMode) {
+	private static LockMode getLockMode(LockModeType lockMode) {
 		switch ( lockMode ) {
 
 			case READ:

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractQueryImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractQueryImpl.java	2009-12-16 18:23:19 UTC (rev 18242)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractQueryImpl.java	2009-12-16 18:23:31 UTC (rev 18243)
@@ -217,7 +217,7 @@
 			}
 			/* TODO:
 			else if ( "org.hibernate.lockMode".equals( hintName ) ) {
-				query.setLockMode( alias, lockMode );
+				query.setAliasLockMode( alias, lockMode );
 			}*/
 			else {
 				skipped = true;
@@ -242,17 +242,10 @@
 		return QueryHints.getDefinedHints();
 	}
 
-	private javax.persistence.LockModeType jpaLockMode = javax.persistence.LockModeType.NONE;
+	public abstract TypedQuery<X> setLockMode(javax.persistence.LockModeType lockModeType);
 
-	public TypedQuery<X> setLockMode(javax.persistence.LockModeType lockModeType) {
-		this.jpaLockMode = lockModeType;
-		return this;
-	}
+	public abstract javax.persistence.LockModeType getLockMode();
 
-	public javax.persistence.LockModeType getLockMode() {
-		return jpaLockMode;
-	}
-
 	private FlushModeType jpaFlushMode;
 
 	public TypedQuery<X> setFlushMode(FlushModeType jpaFlushMode) {

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java	2009-12-16 18:23:19 UTC (rev 18242)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java	2009-12-16 18:23:31 UTC (rev 18243)
@@ -24,11 +24,14 @@
 package org.hibernate.ejb;
 
 import javax.persistence.PersistenceException;
+import javax.persistence.LockModeType;
 
 import org.hibernate.HibernateException;
 import org.hibernate.StaleStateException;
 import org.hibernate.LockOptions;
 
+import java.util.Map;
+
 /**
  * Additional internal contracts for the Hibernate {@link javax.persistence.EntityManager} implementation.
  *
@@ -96,4 +99,13 @@
 	public void throwPersistenceException(HibernateException e);
 
 	public PersistenceException wrapStaleStateException(StaleStateException e);
+
+	/**
+	 * Convert from JPA-2 LockModeType & properties into LockOptions
+	 *
+	 * @param lockModeType is the requested lock type
+	 * @param properties are the lock properties
+	 * @return the LockOptions
+	 */
+	public LockOptions getLockRequest(LockModeType lockModeType, Map<String, Object> properties);
 }

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/QueryImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/QueryImpl.java	2009-12-16 18:23:19 UTC (rev 18242)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/QueryImpl.java	2009-12-16 18:23:31 UTC (rev 18243)
@@ -40,6 +40,7 @@
 import static javax.persistence.TemporalType.TIMESTAMP;
 import javax.persistence.TypedQuery;
 import javax.persistence.PersistenceException;
+import javax.persistence.TransactionRequiredException;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -50,6 +51,7 @@
 import org.hibernate.QueryParameterException;
 import org.hibernate.TypeMismatchException;
 import org.hibernate.SQLQuery;
+import org.hibernate.LockOptions;
 import org.hibernate.engine.query.NamedParameterDescriptor;
 import org.hibernate.engine.query.OrdinalParameterDescriptor;
 import org.hibernate.hql.QueryExecutionRequestException;
@@ -568,4 +570,23 @@
 			}
 		}
 	}
+
+	private javax.persistence.LockModeType jpaLockMode = javax.persistence.LockModeType.NONE;
+
+	@SuppressWarnings({ "unchecked" })
+	public TypedQuery<X> setLockMode(javax.persistence.LockModeType lockModeType) {
+
+		if (! getEntityManager().isTransactionInProgress()) {
+			throw new TransactionRequiredException( "no transaction is in progress" );
+		}
+
+		this.jpaLockMode = lockModeType;
+		query.setLockOptions(getEntityManager().getLockRequest(lockModeType, null));
+		return this;
+	}
+
+	public javax.persistence.LockModeType getLockMode() {
+		return jpaLockMode;
+	}
+
 }

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/TransactionImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/TransactionImpl.java	2009-12-16 18:23:19 UTC (rev 18242)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/TransactionImpl.java	2009-12-16 18:23:31 UTC (rev 18243)
@@ -80,6 +80,9 @@
 			if (e instanceof StaleStateException) {
 				wrappedException = entityManager.wrapStaleStateException( (StaleStateException) e );
 			}
+			else if (e instanceof HibernateException) {
+				throw entityManager.convert( (HibernateException)e );
+			}
 			else {
 				wrappedException = e;
 			}

Modified: core/trunk/envers/src/main/java/org/hibernate/envers/query/impl/AbstractAuditQuery.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/query/impl/AbstractAuditQuery.java	2009-12-16 18:23:19 UTC (rev 18242)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/query/impl/AbstractAuditQuery.java	2009-12-16 18:23:31 UTC (rev 18243)
@@ -219,7 +219,7 @@
         if (cacheMode != null) query.setCacheMode(cacheMode);
         if (timeout != null) query.setTimeout(timeout);
         if (lockOptions != null && lockOptions.getLockMode() != LockMode.NONE) {
-			  query.setLockOptions("e", lockOptions);
+			  query.setLockMode("e", lockOptions.getLockMode());
 		  }
     }
 }

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	2009-12-16 18:23:19 UTC (rev 18242)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/dialect/unit/lockhint/AbstractLockHintTest.java	2009-12-16 18:23:31 UTC (rev 18243)
@@ -1,6 +1,5 @@
 package org.hibernate.test.dialect.unit.lockhint;
 
-import java.util.HashMap;
 import java.util.Collections;
 
 import org.hibernate.junit.UnitTestCase;
@@ -56,8 +55,8 @@
 		}
 
 		public void verify() {
-			HashMap lockOptions = new HashMap();
-			lockOptions.put( aliasToLock, new LockOptions(LockMode.UPGRADE) );
+			LockOptions lockOptions = new LockOptions(LockMode.UPGRADE);
+			lockOptions.setAliasLockMode(LockMode.UPGRADE,  aliasToLock);
 			String actualProcessedSql = dialect.applyLocksToSql( rawSql, lockOptions, Collections.EMPTY_MAP );
 			assertEquals( expectedProcessedSql, actualProcessedSql );
 		}

Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/legacy/FooBarTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/legacy/FooBarTest.java	2009-12-16 18:23:19 UTC (rev 18242)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/legacy/FooBarTest.java	2009-12-16 18:23:31 UTC (rev 18243)
@@ -1355,7 +1355,7 @@
 		s.save(baz);
 		Query q = s.createQuery("from Foo foo, Bar bar");
 		if ( !(getDialect() instanceof DB2Dialect) ) {
-			q.setLockOptions("bar", LockOptions.UPGRADE);
+			q.setLockMode("bar", LockMode.UPGRADE);
 		}
 		Object[] result = (Object[]) q.uniqueResult();
 		Object b = result[0];
@@ -1369,7 +1369,7 @@
 		s.createQuery( "from Foo foo" ).list();
 		assertTrue( s.getCurrentLockMode(b)==LockMode.NONE );
 		q = s.createQuery("from Foo foo");
-		q.setLockOptions("foo", LockOptions.READ);
+		q.setLockMode("foo", LockMode.READ);
 		q.list();
 		assertTrue( s.getCurrentLockMode(b)==LockMode.READ);
 		s.evict(baz);
@@ -1388,9 +1388,9 @@
 		tx = s.beginTransaction();
 		q = s.createQuery("from Foo foo, Bar bar, Bar bar2");
 		if ( !(getDialect() instanceof DB2Dialect) ) {
-			q.setLockOptions("bar", LockOptions.UPGRADE);
+			q.setLockMode("bar", LockMode.UPGRADE);
 		}
-		q.setLockOptions("bar2", LockOptions.READ);
+		q.setLockMode("bar2", LockMode.READ);
 		result = (Object[]) q.list().get(0);
 		if ( !(getDialect() instanceof DB2Dialect) ) {
 			assertTrue( s.getCurrentLockMode( result[0] )==LockMode.UPGRADE && s.getCurrentLockMode( result[1] )==LockMode.UPGRADE );



More information about the hibernate-commits mailing list