Author: steve.ebersole(a)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();
+ }
+}