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

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Tue Feb 2 16:32:54 EST 2010


Author: steve.ebersole at jboss.com
Date: 2010-02-02 16:32:53 -0500 (Tue, 02 Feb 2010)
New Revision: 18682

Added:
   core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/lock/QueryLockingTest.java
Modified:
   core/trunk/core/src/main/java/org/hibernate/action/EntityIncrementVersionProcess.java
   core/trunk/core/src/main/java/org/hibernate/action/EntityVerifyVersionProcess.java
   core/trunk/core/src/main/java/org/hibernate/dialect/lock/OptimisticForceIncrementLockingStrategy.java
   core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticForceIncrementLockingStrategy.java
   core/trunk/core/src/main/java/org/hibernate/event/def/DefaultPostLoadEventListener.java
   core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/FromClause.java
   core/trunk/core/src/main/java/org/hibernate/loader/Loader.java
   core/trunk/core/src/main/java/org/hibernate/loader/hql/QueryLoader.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractQueryImpl.java
   core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/lock/Lock.java
Log:
HHH-4661 - Properly propagate Query.setLockMode to Hibernate Core


Modified: core/trunk/core/src/main/java/org/hibernate/action/EntityIncrementVersionProcess.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/action/EntityIncrementVersionProcess.java	2010-02-02 17:03:05 UTC (rev 18681)
+++ core/trunk/core/src/main/java/org/hibernate/action/EntityIncrementVersionProcess.java	2010-02-02 21:32:53 UTC (rev 18682)
@@ -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.action;
 
@@ -33,8 +32,7 @@
  *
  * @author Scott Marlow
  */
-public class EntityIncrementVersionProcess implements BeforeTransactionCompletionProcess
-{
+public class EntityIncrementVersionProcess implements BeforeTransactionCompletionProcess {
 	private final Object object;
 	private final EntityEntry entry;
 

Modified: core/trunk/core/src/main/java/org/hibernate/action/EntityVerifyVersionProcess.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/action/EntityVerifyVersionProcess.java	2010-02-02 17:03:05 UTC (rev 18681)
+++ core/trunk/core/src/main/java/org/hibernate/action/EntityVerifyVersionProcess.java	2010-02-02 21:32:53 UTC (rev 18682)
@@ -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,23 +20,22 @@
  * Free Software Foundation, Inc.
  * 51 Franklin Street, Fifth Floor
  * Boston, MA  02110-1301  USA
- *
  */
 package org.hibernate.action;
 
+import org.hibernate.OptimisticLockException;
+import org.hibernate.engine.EntityEntry;
 import org.hibernate.engine.SessionImplementor;
-import org.hibernate.engine.EntityEntry;
 import org.hibernate.persister.entity.EntityPersister;
-import org.hibernate.HibernateException;
-import org.hibernate.OptimisticLockException;
+import org.hibernate.pretty.MessageHelper;
 
 /**
  * Verify/Increment the entity version
  *
  * @author Scott Marlow
  */
-public class EntityVerifyVersionProcess implements BeforeTransactionCompletionProcess
-{
+public class EntityVerifyVersionProcess implements BeforeTransactionCompletionProcess {
+	/** @noinspection FieldCanBeLocal,UnusedDeclaration */
 	private final Object object;
 	private final EntityEntry entry;
 
@@ -53,12 +52,13 @@
 	public void doBeforeTransactionCompletion(SessionImplementor session) {
 		final EntityPersister persister = entry.getPersister();
 
-		Object latestVersion = persister.getCurrentVersion(
-			entry.getId(), session
-		);
-	   if(!entry.getVersion().equals(latestVersion))
+		Object latestVersion = persister.getCurrentVersion( entry.getId(), session );
+		if ( !entry.getVersion().equals( latestVersion ) ) {
 			throw new OptimisticLockException(
-				"Newer version ("+ latestVersion+
-				") of entity ("+entry.getEntityName()+") found in database.  id=" +  entry.getId());
+					"Newer version [" + latestVersion +
+							"] of entity [" + MessageHelper.infoString( entry.getEntityName(), entry.getId() ) +
+							"] found in database"
+			);
+		}
 	}
 }
\ No newline at end of file

Modified: core/trunk/core/src/main/java/org/hibernate/dialect/lock/OptimisticForceIncrementLockingStrategy.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/lock/OptimisticForceIncrementLockingStrategy.java	2010-02-02 17:03:05 UTC (rev 18681)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/lock/OptimisticForceIncrementLockingStrategy.java	2010-02-02 21:32:53 UTC (rev 18682)
@@ -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;
 
@@ -30,13 +29,11 @@
 import org.hibernate.JDBCException;
 import org.hibernate.LockMode;
 import org.hibernate.StaleObjectStateException;
-import org.hibernate.event.EventSource;
 import org.hibernate.action.EntityIncrementVersionProcess;
-import org.hibernate.engine.SessionImplementor;
 import org.hibernate.engine.EntityEntry;
+import org.hibernate.engine.SessionImplementor;
+import org.hibernate.event.EventSource;
 import org.hibernate.persister.entity.Lockable;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * An optimistic locking strategy that forces an increment of the version (after verifying that version hasn't changed).
@@ -44,20 +41,18 @@
  * <p/>
  * This strategy is valid for LockMode.OPTIMISTIC_FORCE_INCREMENT
  *
- * @since 3.5
- *
  * @author Scott Marlow
+ * @since 3.5
  */
 public class OptimisticForceIncrementLockingStrategy implements LockingStrategy {
-	private static final Logger log = LoggerFactory.getLogger( OptimisticForceIncrementLockingStrategy.class );
-
 	private final Lockable lockable;
 	private final LockMode lockMode;
-                                             	/**
+
+	/**
 	 * Construct locking strategy.
 	 *
 	 * @param lockable The metadata for the entity to be locked.
-	 * @param lockMode Indictates the type of lock to be acquired.
+	 * @param lockMode Indicates the type of lock to be acquired.
 	 */
 	public OptimisticForceIncrementLockingStrategy(Lockable lockable, LockMode lockMode) {
 		this.lockable = lockable;
@@ -67,22 +62,22 @@
 		}
 	}
 
-   /**
+	/**
 	 * @see LockingStrategy#lock
 	 */
 	public void lock(
-      Serializable id,
-      Object version,
-      Object object,
-      int timeout, SessionImplementor session) throws StaleObjectStateException, JDBCException {
+			Serializable id,
+			Object version,
+			Object object,
+			int timeout, SessionImplementor session) throws StaleObjectStateException, JDBCException {
 		if ( !lockable.isVersioned() ) {
 			throw new HibernateException( "[" + lockMode + "] not supported for non-versioned entities [" + lockable.getEntityName() + "]" );
 		}
-      EntityEntry entry = session.getPersistenceContext().getEntry(object);
-		EntityIncrementVersionProcess incrementVersion = new EntityIncrementVersionProcess(object, entry);
-		EventSource source = (EventSource)session;
+		EntityEntry entry = session.getPersistenceContext().getEntry( object );
+		EntityIncrementVersionProcess incrementVersion = new EntityIncrementVersionProcess( object, entry );
+		EventSource source = (EventSource) session;
 		// Register the EntityIncrementVersionProcess action to run just prior to transaction commit. 
-		source.getActionQueue().registerProcess(incrementVersion);
+		source.getActionQueue().registerProcess( incrementVersion );
 	}
 
 	protected LockMode getLockMode() {

Modified: core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticForceIncrementLockingStrategy.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticForceIncrementLockingStrategy.java	2010-02-02 17:03:05 UTC (rev 18681)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticForceIncrementLockingStrategy.java	2010-02-02 21:32:53 UTC (rev 18682)
@@ -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;
 
@@ -30,25 +29,20 @@
 import org.hibernate.JDBCException;
 import org.hibernate.LockMode;
 import org.hibernate.StaleObjectStateException;
-import org.hibernate.engine.SessionImplementor;
 import org.hibernate.engine.EntityEntry;
-import org.hibernate.persister.entity.Lockable;
+import org.hibernate.engine.SessionImplementor;
 import org.hibernate.persister.entity.EntityPersister;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.hibernate.persister.entity.Lockable;
 
 /**
  * A pessimistic locking strategy that increments the version immediately (obtaining an exclusive write lock).
  * <p/>
  * This strategy is valid for LockMode.PESSIMISTIC_FORCE_INCREMENT
  *
- * @since 3.5
- *
  * @author Scott Marlow
+ * @since 3.5
  */
 public class PessimisticForceIncrementLockingStrategy implements LockingStrategy {
-	private static final Logger log = LoggerFactory.getLogger( PessimisticForceIncrementLockingStrategy.class );
-
 	private final Lockable lockable;
 	private final LockMode lockMode;
 
@@ -56,7 +50,7 @@
 	 * Construct locking strategy.
 	 *
 	 * @param lockable The metadata for the entity to be locked.
-	 * @param lockMode Indictates the type of lock to be acquired.
+	 * @param lockMode Indicates the type of lock to be acquired.
 	 */
 	public PessimisticForceIncrementLockingStrategy(Lockable lockable, LockMode lockMode) {
 		this.lockable = lockable;
@@ -67,26 +61,29 @@
 		}
 	}
 
-   /**
-	 * @see org.hibernate.dialect.lock.LockingStrategy#lock
+	/**
+	 * {@inheritDoc}
 	 */
 	public void lock(
-      Serializable id,
-      Object version,
-      Object object,
-      int timeout,
-		SessionImplementor session) throws StaleObjectStateException, JDBCException {
+			Serializable id,
+			Object version,
+			Object object,
+			int timeout,
+			SessionImplementor session) throws StaleObjectStateException, JDBCException {
 		if ( !lockable.isVersioned() ) {
 			throw new HibernateException( "[" + lockMode + "] not supported for non-versioned entities [" + lockable.getEntityName() + "]" );
 		}
-      EntityEntry entry = session.getPersistenceContext().getEntry(object);
-      final EntityPersister persister = entry.getPersister();
-      Object nextVersion = persister.forceVersionIncrement(
-            entry.getId(), entry.getVersion(), session
-      );
-      entry.forceLocked( object, nextVersion );
+		EntityEntry entry = session.getPersistenceContext().getEntry( object );
+		final EntityPersister persister = entry.getPersister();
+		Object nextVersion = persister.forceVersionIncrement( entry.getId(), entry.getVersion(), session );
+		entry.forceLocked( object, nextVersion );
 	}
 
+	/**
+	 * Retrieve the specific lock mode defined.
+	 *
+	 * @return The specific lock mode.
+	 */
 	protected LockMode getLockMode() {
 		return lockMode;
 	}

Modified: core/trunk/core/src/main/java/org/hibernate/event/def/DefaultPostLoadEventListener.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/event/def/DefaultPostLoadEventListener.java	2010-02-02 17:03:05 UTC (rev 18681)
+++ core/trunk/core/src/main/java/org/hibernate/event/def/DefaultPostLoadEventListener.java	2010-02-02 21:32:53 UTC (rev 18682)
@@ -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,22 +20,54 @@
  * Free Software Foundation, Inc.
  * 51 Franklin Street, Fifth Floor
  * Boston, MA  02110-1301  USA
- *
  */
 package org.hibernate.event.def;
 
+import org.hibernate.AssertionFailure;
+import org.hibernate.LockMode;
+import org.hibernate.action.EntityIncrementVersionProcess;
+import org.hibernate.action.EntityVerifyVersionProcess;
 import org.hibernate.classic.Lifecycle;
+import org.hibernate.engine.EntityEntry;
 import org.hibernate.event.PostLoadEvent;
 import org.hibernate.event.PostLoadEventListener;
+import org.hibernate.persister.entity.EntityPersister;
 
 /**
- * Call <tt>Lifecycle</tt> interface if necessary
+ * We do 2 things here:<ul>
+ * <li>Call {@link Lifecycle} interface if necessary</li>
+ * <li>Perform needed {@link EntityEntry#getLockMode()} related processing</li>
+ * </ul>
  *
  * @author Gavin King
+ * @author Steve Ebersole
  */
 public class DefaultPostLoadEventListener implements PostLoadEventListener {
 	
 	public void onPostLoad(PostLoadEvent event) {
+		final Object entity = event.getEntity();
+		final EntityEntry entry = event.getSession().getPersistenceContext().getEntry( entity );
+		if ( entry == null ) {
+			throw new AssertionFailure( "possible non-threadsafe access to the session" );
+		}
+
+		final LockMode lockMode = entry.getLockMode();
+		if ( LockMode.PESSIMISTIC_FORCE_INCREMENT.equals( lockMode ) ) {
+			final EntityPersister persister = entry.getPersister();
+			Object nextVersion = persister.forceVersionIncrement(
+					entry.getId(), entry.getVersion(), event.getSession()
+			);
+			entry.forceLocked( entity, nextVersion );
+		}
+		else if ( LockMode.OPTIMISTIC_FORCE_INCREMENT.equals( lockMode ) ) {
+			EntityIncrementVersionProcess incrementVersion = new EntityIncrementVersionProcess( entity, entry );
+			event.getSession().getActionQueue().registerProcess( incrementVersion );
+		}
+		else if ( LockMode.OPTIMISTIC.equals( lockMode ) ) {
+			EntityVerifyVersionProcess verifyVersion = new EntityVerifyVersionProcess( entity, entry );
+			event.getSession().getActionQueue().registerProcess( verifyVersion );
+		}
+
 		if ( event.getPersister().implementsLifecycle( event.getSession().getEntityMode() ) ) {
 			//log.debug( "calling onLoad()" );
 			( ( Lifecycle ) event.getEntity() ).onLoad( event.getSession(), event.getId() );

Modified: core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/FromClause.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/FromClause.java	2010-02-02 17:03:05 UTC (rev 18681)
+++ core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/FromClause.java	2010-02-02 21:32:53 UTC (rev 18682)
@@ -136,6 +136,27 @@
 		return fromElement;
 	}
 
+	public FromElement findFromElementBySqlAlias(String sqlAlias) {
+		FromElement fromElement = ( FromElement ) fromElementByTableAlias.get( sqlAlias );
+		if ( fromElement == null && parentFromClause != null ) {
+			fromElement = parentFromClause.getFromElement( sqlAlias );
+		}
+		return fromElement;
+	}
+
+	public FromElement findFromElementByUserOrSqlAlias(String userAlias, String sqlAlias) {
+		FromElement fromElement = null;
+		if ( userAlias != null ) {
+			fromElement = getFromElement( userAlias );
+		}
+
+		if ( fromElement == null ) {
+			fromElement = findFromElementBySqlAlias( sqlAlias );
+		}
+
+		return fromElement;
+	}
+
 	private FromElement findIntendedAliasedFromElementBasedOnCrazyJPARequirements(String specifiedAlias) {
 		Iterator itr = fromElementByClassAlias.entrySet().iterator();
 		while ( itr.hasNext() ) {

Modified: core/trunk/core/src/main/java/org/hibernate/loader/Loader.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/loader/Loader.java	2010-02-02 17:03:05 UTC (rev 18681)
+++ core/trunk/core/src/main/java/org/hibernate/loader/Loader.java	2010-02-02 21:32:53 UTC (rev 18682)
@@ -643,10 +643,15 @@
 			}
 		}
 
+		applyPostLoadLocks( row, lockModesArray, session );
+
 		return getResultColumnOrRow( row, queryParameters.getResultTransformer(), resultSet, session );
 
 	}
 
+	protected void applyPostLoadLocks(Object[] row, LockMode[] lockModesArray, SessionImplementor session) {
+	}
+
 	/**
 	 * Read any collection elements contained in a single row of the result set
 	 */

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-02-02 17:03:05 UTC (rev 18681)
+++ core/trunk/core/src/main/java/org/hibernate/loader/hql/QueryLoader.java	2010-02-02 21:32:53 UTC (rev 18682)
@@ -39,6 +39,7 @@
 import org.hibernate.ScrollableResults;
 import org.hibernate.LockOptions;
 import org.hibernate.dialect.Dialect;
+import org.hibernate.engine.EntityEntry;
 import org.hibernate.engine.QueryParameters;
 import org.hibernate.engine.SessionFactoryImplementor;
 import org.hibernate.engine.SessionImplementor;
@@ -281,43 +282,50 @@
 	 * @param lockOptions a collection of lock modes specified dynamically via the Query interface
 	 */
 	protected LockMode[] getLockModes(LockOptions lockOptions) {
+		if ( lockOptions == null ) {
+			return defaultLockModes;
+		}
 
-		if ( lockOptions == null ||
-			lockOptions.getAliasLockCount() == 0 ) {
+		if ( lockOptions.getAliasLockCount() == 0
+				&& ( lockOptions.getLockMode() == null || LockMode.NONE.equals( lockOptions.getLockMode() ) ) ) {
 			return defaultLockModes;
 		}
-		else {
-			// unfortunately this stuff can't be cached because
-			// it is per-invocation, not constant for the
-			// QueryTranslator instance
 
-			LockMode[] lockModesArray = new LockMode[entityAliases.length];
-			for ( int i = 0; i < entityAliases.length; i++ ) {
-				LockMode lockMode = lockOptions.getEffectiveLockMode( entityAliases[i] );
-				if ( lockMode == null ) {
-					//NONE, because its the requested lock mode, not the actual! 
-					lockMode = LockMode.NONE;
-				}
-				lockModesArray[i] = lockMode;
+		// unfortunately this stuff can't be cached because
+		// it is per-invocation, not constant for the
+		// QueryTranslator instance
+
+		LockMode[] lockModesArray = new LockMode[entityAliases.length];
+		for ( int i = 0; i < entityAliases.length; i++ ) {
+			LockMode lockMode = lockOptions.getEffectiveLockMode( entityAliases[i] );
+			if ( lockMode == null ) {
+				//NONE, because its the requested lock mode, not the actual!
+				lockMode = LockMode.NONE;
 			}
-			return lockModesArray;
+			lockModesArray[i] = lockMode;
 		}
+
+		return lockModesArray;
 	}
 
 	protected String applyLocks(String sql, LockOptions lockOptions, Dialect dialect) throws QueryException {
+		// 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
+
 		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
+		// we need both the set of locks and the columns to reference in locks
+		// as the ultimate output of this section...
 		final LockOptions locks = new LockOptions( lockOptions.getLockMode() );
+		final Map keyColumnNames = dialect.forUpdateOfColumns() ? new HashMap() : null;
+
 		locks.setScope( lockOptions.getScope() );
 		locks.setTimeOut( lockOptions.getTimeOut() );
 
-		final Map keyColumnNames = dialect.forUpdateOfColumns() ? new HashMap() : null;
 		final Iterator itr = sqlAliasByEntityAlias.entrySet().iterator();
 		while ( itr.hasNext() ) {
 			final Map.Entry entry = (Map.Entry) itr.next();
@@ -333,7 +341,9 @@
 			// want to apply the lock against the root table (for all other strategies,
 			// it just happens that driving and root are the same).
 			final QueryNode select = ( QueryNode ) queryTranslator.getSqlAST();
-			final Lockable drivingPersister = ( Lockable ) select.getFromClause().getFromElement( userAlias ).getQueryable();
+			final Lockable drivingPersister = ( Lockable ) select.getFromClause()
+					.findFromElementByUserOrSqlAlias( userAlias, drivingSqlAlias )
+					.getQueryable();
 			final String sqlAlias = drivingPersister.getRootTableAlias( drivingSqlAlias );
 
 			final LockMode effectiveLockMode = lockOptions.getEffectiveLockMode( userAlias );
@@ -344,9 +354,26 @@
 			}
 		}
 
+		// apply the collected locks and columns
 		return dialect.applyLocksToSql( sql, locks, keyColumnNames );
 	}
 
+	protected void applyPostLoadLocks(Object[] row, LockMode[] lockModesArray, SessionImplementor session) {
+		// todo : scalars???
+//		if ( row.length != lockModesArray.length ) {
+//			return;
+//		}
+//
+//		for ( int i = 0; i < lockModesArray.length; i++ ) {
+//			if ( LockMode.OPTIMISTIC_FORCE_INCREMENT.equals( lockModesArray[i] ) ) {
+//				final EntityEntry pcEntry =
+//			}
+//			else if ( LockMode.PESSIMISTIC_FORCE_INCREMENT.equals( lockModesArray[i] ) ) {
+//
+//			}
+//		}
+	}
+
 	protected boolean upgradeLocks() {
 		return true;
 	}

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractQueryImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractQueryImpl.java	2010-02-02 17:03:05 UTC (rev 18681)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractQueryImpl.java	2010-02-02 21:32:53 UTC (rev 18682)
@@ -259,7 +259,7 @@
 				}
 				else {
 					// extract the alias
-					final String alias = hintName.substring( AvailableSettings.ALIAS_SPECIFIC_LOCK_MODE.length() );
+					final String alias = hintName.substring( AvailableSettings.ALIAS_SPECIFIC_LOCK_MODE.length() + 1 );
 					// determine the LockMode
 					try {
 						final LockMode lockMode = LockModeTypeHelper.interpretLockMode( value );

Modified: core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/lock/Lock.java
===================================================================
--- core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/lock/Lock.java	2010-02-02 17:03:05 UTC (rev 18681)
+++ core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/lock/Lock.java	2010-02-02 21:32:53 UTC (rev 18682)
@@ -15,6 +15,13 @@
 	private Integer version;
 	private String name;
 
+	public Lock() {
+	}
+
+	public Lock(String name) {
+		this.name = name;
+	}
+
 	@Id
 	@GeneratedValue
 	public Integer getId() {

Added: core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/lock/QueryLockingTest.java
===================================================================
--- core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/lock/QueryLockingTest.java	                        (rev 0)
+++ core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/lock/QueryLockingTest.java	2010-02-02 21:32:53 UTC (rev 18682)
@@ -0,0 +1,95 @@
+/*
+ * 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.test.lock;
+
+import javax.persistence.EntityManager;
+import javax.persistence.LockModeType;
+
+import org.hibernate.LockMode;
+import org.hibernate.Session;
+import org.hibernate.ejb.AvailableSettings;
+import org.hibernate.ejb.QueryImpl;
+import org.hibernate.ejb.test.TestCase;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public class QueryLockingTest extends TestCase {
+
+	@Override
+	protected Class<?>[] getAnnotatedClasses() {
+		return new Class[] { Lock.class };
+	}
+
+	public void testOverallLockMode() {
+		EntityManager em = getOrCreateEntityManager();
+		em.getTransaction().begin();
+		QueryImpl jpaQuery = em.createQuery( "from Lock_ l" ).unwrap( QueryImpl.class );
+
+		org.hibernate.impl.QueryImpl hqlQuery = (org.hibernate.impl.QueryImpl) jpaQuery.getHibernateQuery();
+		assertEquals( LockMode.NONE, hqlQuery.getLockOptions().getLockMode() );
+		assertNull( hqlQuery.getLockOptions().getAliasSpecificLockMode( "l" ) );
+		assertEquals( LockMode.NONE, hqlQuery.getLockOptions().getEffectiveLockMode( "l" ) );
+
+		// NOTE : LockModeType.READ should map to LockMode.OPTIMISTIC
+		jpaQuery.setLockMode( LockModeType.READ );
+		assertEquals( LockMode.OPTIMISTIC, hqlQuery.getLockOptions().getLockMode() );
+		assertNull( hqlQuery.getLockOptions().getAliasSpecificLockMode( "l" ) );
+		assertEquals( LockMode.OPTIMISTIC, hqlQuery.getLockOptions().getEffectiveLockMode( "l" ) );
+
+		jpaQuery.setHint( AvailableSettings.ALIAS_SPECIFIC_LOCK_MODE+".l", LockModeType.PESSIMISTIC_WRITE );
+		assertEquals( LockMode.OPTIMISTIC, hqlQuery.getLockOptions().getLockMode() );
+		assertEquals( LockMode.PESSIMISTIC_WRITE, hqlQuery.getLockOptions().getAliasSpecificLockMode( "l" ) );
+		assertEquals( LockMode.PESSIMISTIC_WRITE, hqlQuery.getLockOptions().getEffectiveLockMode( "l" ) );
+
+		em.getTransaction().commit();
+		em.close();
+	}
+
+	public void testForcedIncrementOverall() {
+		EntityManager em = getOrCreateEntityManager();
+		em.getTransaction().begin();
+		Lock lock = new Lock( "name" );
+		em.persist( lock );
+		em.getTransaction().commit();
+		em.close();
+		Integer initial = lock.getVersion();
+		assertNotNull( initial );
+
+		em = getOrCreateEntityManager();
+		em.getTransaction().begin();
+		Lock reread = em.createQuery( "from Lock_", Lock.class ).setLockMode( LockModeType.PESSIMISTIC_FORCE_INCREMENT ).getSingleResult();
+		em.getTransaction().commit();
+		em.close();
+		assertFalse( reread.getVersion().equals( initial ) );
+
+		em = getOrCreateEntityManager();
+		em.getTransaction().begin();
+		em.remove( em.getReference( Lock.class, reread.getId() ) );
+		em.getTransaction().commit();
+		em.close();
+	}
+}



More information about the hibernate-commits mailing list