Author: steve.ebersole(a)jboss.com
Date: 2010-02-01 14:42:16 -0500 (Mon, 01 Feb 2010)
New Revision: 18675
Added:
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/util/LockModeTypeHelper.java
Modified:
core/trunk/core/src/main/java/org/hibernate/LockOptions.java
core/trunk/core/src/main/java/org/hibernate/hql/classic/QueryTranslatorImpl.java
core/trunk/core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java
core/trunk/core/src/main/java/org/hibernate/impl/AbstractQueryImpl.java
core/trunk/core/src/main/java/org/hibernate/impl/QueryImpl.java
core/trunk/core/src/main/java/org/hibernate/loader/criteria/CriteriaLoader.java
core/trunk/core/src/main/java/org/hibernate/loader/criteria/CriteriaQueryTranslator.java
core/trunk/core/src/main/java/org/hibernate/loader/hql/QueryLoader.java
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractQueryImpl.java
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AvailableSettings.java
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/QueryImpl.java
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/util/CacheModeHelper.java
core/trunk/testsuite/src/test/java/org/hibernate/test/dialect/unit/lockhint/AbstractLockHintTest.java
Log:
HHH-4661 - Properly propagate Query.setLockMode to Hibernate Core
Modified: core/trunk/core/src/main/java/org/hibernate/LockOptions.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/LockOptions.java 2010-01-31 21:50:23 UTC
(rev 18674)
+++ core/trunk/core/src/main/java/org/hibernate/LockOptions.java 2010-02-01 19:42:16 UTC
(rev 18675)
@@ -35,17 +35,8 @@
*
* @author Scott Marlow
*/
-public class LockOptions implements Serializable
-{
+public class LockOptions implements Serializable {
/**
- * NO_WAIT timeout value will not block for pessimistic locking
- */
- public static final int NO_WAIT = 0;
- /**
- * WAIT_FOREVER timeout value will block until pessimistic lock is obtained
- */
- public static final int WAIT_FOREVER = -1;
- /**
* NONE represents LockMode.NONE (timeout + scope do not apply)
*/
public static final LockOptions NONE = new LockOptions(LockMode.NONE);
@@ -59,15 +50,6 @@
*/
public static final LockOptions UPGRADE = new LockOptions(LockMode.UPGRADE);
- private LockMode lockMode = LockMode.NONE;
-
- private int timeout = WAIT_FOREVER; // timeout in milliseconds, 0 = no wait, -1 = wait
indefinitely
-
- private boolean scope=false;// if true, cascade (pessimistic only) lock to collections
and relationships
- // owned by the entity.
-
- private Map /* <String, LockMode> */ lockModesByName = new HashMap();
-
public LockOptions() {
}
@@ -75,110 +57,173 @@
this.lockMode = lockMode;
}
+ private LockMode lockMode = LockMode.NONE;
+
/**
- * Get the lock mode.
- * @return the lock mode.
+ * Retrieve the overall lock mode in effect for this set of options.
+ * <p/>
+ * In certain contexts (hql and criteria), lock-modes can be defined in an
+ * even more granular {@link #setAliasSpecificLockMode(String, LockMode) per-alias}
fashion
+ *
+ * @return The overall lock mode.
*/
public LockMode getLockMode() {
return lockMode;
}
/**
- * Specify the LockMode to be used. The default is LockMode.none.
+ * Set the overall {@link LockMode} to be used. The default is
+ * {@link LockMode#NONE}
*
- * @param lockMode
- * @return this LockRequest instance for operation chaining.
+ * @param lockMode The new overall lock mode to use.
+ *
+ * @return this (for method chaining).
*/
public LockOptions setLockMode(LockMode lockMode) {
this.lockMode = lockMode;
return this;
}
+ private Map aliasSpecificLockModes = new HashMap();
+
/**
- * Specify the LockMode to be used for the specified alias.
+ * Specify the {@link LockMode} to be used for a specific query alias.
*
- * The ability to set the lockMode for a table alias is intended
- * for internal Hibernate use.
- *
- * @param lockMode
* @param alias used to reference the LockMode.
+ * @param lockMode The lock mode to apply to the given alias
* @return this LockRequest instance for operation chaining.
+ *
+ * @see Query#setLockMode(String, LockMode)
+ * @see Criteria#setLockMode(LockMode)
+ * @see Criteria#setLockMode(String, LockMode)
*/
- public LockOptions setAliasLockMode(LockMode lockMode, String alias) {
- lockModesByName.put(alias, lockMode);
+ public LockOptions setAliasSpecificLockMode(String alias, LockMode lockMode) {
+ aliasSpecificLockModes.put( alias, lockMode );
return this;
}
/**
- * Get the lock mode for the specified alias.
+ * Get the {@link LockMode} explicitly specified for the given alias via
+ * {@link #setAliasSpecificLockMode}
+ * <p/>
+ * Differs from {@link #getEffectiveLockMode} in that here we only return
+ * explicitly specified alias-specific lock modes.
*
- * @param alias used to reference the LockMode.
- * @return the lock mode.
+ * @param alias The alias for which to locate the explicit lock mode.
+ *
+ * @return The explicit lock mode for that alias.
*/
- public LockMode getAliasLockMode(String alias) {
- return (LockMode)lockModesByName.get(alias);
+ public LockMode getAliasSpecificLockMode(String alias) {
+ return (LockMode) aliasSpecificLockModes.get( alias );
}
/**
- * Get the number of aliases that have LockModes specified
+ * Determine the {@link LockMode} to apply to the given alias. If no
+ * mode was explicitly {@link #setAliasSpecificLockMode set}, the
+ * {@link #getLockMode overall mode} is returned. If the overall lock mode is
+ * <tt>null</tt> as well, {@link LockMode#NONE} is returned.
+ * <p/>
+ * Differs from {@link #getAliasSpecificLockMode} in that here we fallback to we only
return
+ * the overall lock mode.
*
- * @return the number of aliases
+ * @param alias The alias for which to locate the effective lock mode.
+ *
+ * @return The effective lock mode.
*/
+ public LockMode getEffectiveLockMode(String alias) {
+ LockMode lockMode = getAliasSpecificLockMode( alias );
+ if ( lockMode == null ) {
+ lockMode = this.lockMode;
+ }
+ return lockMode == null ? LockMode.NONE : lockMode;
+ }
+
+ /**
+ * Get the number of aliases that have specific lock modes defined.
+ *
+ * @return the number of explicitly defined alias lock modes.
+ */
public int getAliasLockCount() {
- return lockModesByName.size();
+ return aliasSpecificLockModes.size();
}
/**
* Iterator for accessing Alias (key) and LockMode (value) as Map.Entry
- *
+ *
* @return Iterator for accessing the Map.Entry's
*/
public Iterator getAliasLockIterator() {
- return lockModesByName.entrySet().iterator();
+ return aliasSpecificLockModes.entrySet().iterator();
}
/**
- * Get the timeout setting.
+ * Indicates that the database should not wait at all to acquire the pessimistic lock.
+ * @see #getTimeOut
+ */
+ public static final int NO_WAIT = 0;
+ /**
+ * Indicates that there is no timeout for the acquisition.
+ * @see #getTimeOut
+ */
+ public static final int WAIT_FOREVER = -1;
+
+ private int timeout = WAIT_FOREVER;
+
+ /**
+ * Retrieve the current timeout setting.
+ * <p/>
+ * The timeout is the amount of time, in milliseconds, we should instruct the database
+ * to wait for any requested pessimistic lock acquisition.
+ * <p/>
+ * {@link #NO_WAIT} and {@link #WAIT_FOREVER} represent 2 "magic" values.
*
- * @return timeout in milliseconds, -1 for indefinite wait and 0 for no wait.
+ * @return timeout in milliseconds, or {@link #NO_WAIT} or {@link #WAIT_FOREVER}
*/
public int getTimeOut() {
return timeout;
}
/**
- * Specify the pessimistic lock timeout (check if your dialect supports this option).
- * The default pessimistic lock behavior is to wait forever for the lock.
+ * Set the timeout setting.
+ * <p/>
+ * See {@link #getTimeOut} for a discussion of meaning.
*
- * @param timeout is time in milliseconds to wait for lock. -1 means wait forever and 0
means no wait.
- * @return this LockRequest instance for operation chaining.
+ * @param timeout The new timeout setting.
+ *
+ * @return this (for method chaining).
+ *
+ * @see #getTimeOut
*/
public LockOptions setTimeOut(int timeout) {
this.timeout = timeout;
return this;
}
+ private boolean scope=false;
+
/**
- * Check if locking is cascaded to owned collections and relationships.
- * @return true if locking will be extended to owned collections and relationships.
+ * Retrieve the current lock scope setting.
+ * <p/>
+ * "scope" is a JPA defined term. It is basically a cascading of the lock to
associations.
+ *
+ * @return true if locking will be extended to owned associations
*/
public boolean getScope() {
return scope;
}
/**
- * Specify if LockMode should be cascaded to owned collections and relationships.
- * The association must be mapped with <tt>cascade="lock" for scope=true
to work.
+ * Set the cope.
*
- * @param scope
- * @return
+ * @param scope The new scope setting
+ *
+ * @return this (for method chaining).
*/
public LockOptions setScope(boolean scope) {
this.scope = scope;
return this;
}
-
/**
* Shallow copy From to Dest
*
@@ -190,7 +235,7 @@
dest.setLockMode(from.getLockMode());
dest.setScope(from.getScope());
dest.setTimeOut(from.getTimeOut());
- dest.lockModesByName = new HashMap(from.lockModesByName);
+ dest.aliasSpecificLockModes = new HashMap(from.aliasSpecificLockModes );
return dest;
}
}
Modified:
core/trunk/core/src/main/java/org/hibernate/hql/classic/QueryTranslatorImpl.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/hql/classic/QueryTranslatorImpl.java 2010-01-31
21:50:23 UTC (rev 18674)
+++
core/trunk/core/src/main/java/org/hibernate/hql/classic/QueryTranslatorImpl.java 2010-02-01
19:42:16 UTC (rev 18675)
@@ -1080,7 +1080,7 @@
Iterator iter = lockOptions.getAliasLockIterator();
while ( iter.hasNext() ) {
Map.Entry me = ( Map.Entry ) iter.next();
- locks.setAliasLockMode( (LockMode) me.getValue(), getAliasName( ( String )
me.getKey() ) );
+ locks.setAliasSpecificLockMode( getAliasName( ( String ) me.getKey() ), (LockMode)
me.getValue() );
}
Map keyColumnNames = null;
if ( dialect.forUpdateOfColumns() ) {
Modified: core/trunk/core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java 2010-01-31
21:50:23 UTC (rev 18674)
+++ core/trunk/core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java 2010-02-01
19:42:16 UTC (rev 18675)
@@ -429,7 +429,7 @@
" from " + tableName + ' ' + alias +
" where " + StringHelper.qualify( alias, segmentColumnName ) +
"=?";
LockOptions lockOptions = new LockOptions(LockMode.UPGRADE);
- lockOptions.setAliasLockMode(LockMode.UPGRADE, alias);
+ lockOptions.setAliasSpecificLockMode( alias, LockMode.UPGRADE );
Map updateTargetColumnsMap = Collections.singletonMap( alias, new String[] {
valueColumnName } );
return dialect.applyLocksToSql( query, lockOptions, updateTargetColumnsMap );
}
Modified: core/trunk/core/src/main/java/org/hibernate/impl/AbstractQueryImpl.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/impl/AbstractQueryImpl.java 2010-01-31
21:50:23 UTC (rev 18674)
+++ core/trunk/core/src/main/java/org/hibernate/impl/AbstractQueryImpl.java 2010-02-01
19:42:16 UTC (rev 18675)
@@ -241,7 +241,7 @@
return session;
}
- protected abstract LockOptions getLockOptions();
+ public abstract LockOptions getLockOptions();
// Parameter handling code ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Modified: core/trunk/core/src/main/java/org/hibernate/impl/QueryImpl.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/impl/QueryImpl.java 2010-01-31 21:50:23
UTC (rev 18674)
+++ core/trunk/core/src/main/java/org/hibernate/impl/QueryImpl.java 2010-02-01 19:42:16
UTC (rev 18675)
@@ -125,7 +125,7 @@
}
public Query setLockMode(String alias, LockMode lockMode) {
- lockOptions.setAliasLockMode(lockMode, alias);
+ lockOptions.setAliasSpecificLockMode( alias, lockMode );
return this;
}
@@ -136,7 +136,7 @@
return this;
}
- protected LockOptions getLockOptions() {
+ public LockOptions getLockOptions() {
return lockOptions;
}
Modified: core/trunk/core/src/main/java/org/hibernate/loader/criteria/CriteriaLoader.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/loader/criteria/CriteriaLoader.java 2010-01-31
21:50:23 UTC (rev 18674)
+++
core/trunk/core/src/main/java/org/hibernate/loader/criteria/CriteriaLoader.java 2010-02-01
19:42:16 UTC (rev 18675)
@@ -157,11 +157,11 @@
final Map keyColumnNames = dialect.forUpdateOfColumns() ? new HashMap() : null;
final String[] drivingSqlAliases = getAliases();
for ( int i = 0; i < drivingSqlAliases.length; i++ ) {
- final LockMode lockMode = lockOptions.getAliasLockMode( drivingSqlAliases[i] );
+ final LockMode lockMode = lockOptions.getAliasSpecificLockMode( drivingSqlAliases[i]
);
if ( lockMode != null ) {
final Lockable drivingPersister = ( Lockable ) getEntityPersisters()[i];
final String rootSqlAlias = drivingPersister.getRootTableAlias( drivingSqlAliases[i]
);
- locks.setAliasLockMode(lockMode, rootSqlAlias);
+ locks.setAliasSpecificLockMode( rootSqlAlias, lockMode );
if ( keyColumnNames != null ) {
keyColumnNames.put( rootSqlAlias,
drivingPersister.getRootTableIdentifierColumnNames() );
}
@@ -178,7 +178,7 @@
final int size = entityAliases.length;
LockMode[] lockModesArray = new LockMode[size];
for ( int i=0; i<size; i++ ) {
- LockMode lockMode = lockOptions.getAliasLockMode( entityAliases[i] );
+ LockMode lockMode = lockOptions.getAliasSpecificLockMode( entityAliases[i] );
lockModesArray[i] = lockMode==null ? lockOptions.getLockMode() : lockMode;
}
return lockModesArray;
Modified:
core/trunk/core/src/main/java/org/hibernate/loader/criteria/CriteriaQueryTranslator.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/loader/criteria/CriteriaQueryTranslator.java 2010-01-31
21:50:23 UTC (rev 18674)
+++
core/trunk/core/src/main/java/org/hibernate/loader/criteria/CriteriaQueryTranslator.java 2010-02-01
19:42:16 UTC (rev 18675)
@@ -284,7 +284,7 @@
while ( iter.hasNext() ) {
Map.Entry me = ( Map.Entry ) iter.next();
final Criteria subcriteria = getAliasedCriteria( ( String ) me.getKey() );
- lockOptions.setAliasLockMode( (LockMode)me.getValue(), getSQLAlias( subcriteria ) );
+ lockOptions.setAliasSpecificLockMode( getSQLAlias( subcriteria ),
(LockMode)me.getValue() );
}
List values = new ArrayList();
List types = new ArrayList();
@@ -293,7 +293,7 @@
CriteriaImpl.Subcriteria subcriteria = ( CriteriaImpl.Subcriteria ) iter.next();
LockMode lm = subcriteria.getLockMode();
if ( lm != null ) {
- lockOptions.setAliasLockMode( lm, getSQLAlias( subcriteria ) );
+ lockOptions.setAliasSpecificLockMode( getSQLAlias( subcriteria ), lm );
}
if ( subcriteria.getWithClause() != null )
{
Modified: core/trunk/core/src/main/java/org/hibernate/loader/hql/QueryLoader.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/loader/hql/QueryLoader.java 2010-01-31
21:50:23 UTC (rev 18674)
+++ core/trunk/core/src/main/java/org/hibernate/loader/hql/QueryLoader.java 2010-02-01
19:42:16 UTC (rev 18675)
@@ -28,6 +28,7 @@
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -292,10 +293,10 @@
LockMode[] lockModesArray = new LockMode[entityAliases.length];
for ( int i = 0; i < entityAliases.length; i++ ) {
- LockMode lockMode = lockOptions.getAliasLockMode( entityAliases[i] );
+ LockMode lockMode = lockOptions.getEffectiveLockMode( entityAliases[i] );
if ( lockMode == null ) {
//NONE, because its the requested lock mode, not the actual!
- lockMode = lockOptions.getLockMode();
+ lockMode = LockMode.NONE;
}
lockModesArray[i] = lockMode;
}
@@ -312,16 +313,16 @@
// can't cache this stuff either (per-invocation)
// we are given a map of user-alias -> lock mode
// create a new map of sql-alias -> lock mode
- final LockOptions locks = new LockOptions(lockOptions.getLockMode());
- locks.setScope( lockOptions.getScope());
- locks.setTimeOut( lockOptions.getTimeOut());
+ final LockOptions locks = new LockOptions( lockOptions.getLockMode() );
+ locks.setScope( lockOptions.getScope() );
+ locks.setTimeOut( lockOptions.getTimeOut() );
final Map keyColumnNames = dialect.forUpdateOfColumns() ? new HashMap() : null;
- final Iterator iter = lockOptions.getAliasLockIterator();
- while ( iter.hasNext() ) {
- Map.Entry me = ( Map.Entry ) iter.next();
- final String userAlias = ( String ) me.getKey();
- final String drivingSqlAlias = ( String ) sqlAliasByEntityAlias.get( userAlias );
+ final Iterator itr = sqlAliasByEntityAlias.entrySet().iterator();
+ while ( itr.hasNext() ) {
+ final Map.Entry entry = (Map.Entry) itr.next();
+ final String userAlias = (String) entry.getKey();
+ final String drivingSqlAlias = (String) entry.getValue();
if ( drivingSqlAlias == null ) {
throw new IllegalArgumentException( "could not locate alias to apply lock mode :
" + userAlias );
}
@@ -334,11 +335,15 @@
final QueryNode select = ( QueryNode ) queryTranslator.getSqlAST();
final Lockable drivingPersister = ( Lockable ) select.getFromClause().getFromElement(
userAlias ).getQueryable();
final String sqlAlias = drivingPersister.getRootTableAlias( drivingSqlAlias );
- locks.setAliasLockMode( (LockMode)me.getValue(), sqlAlias);
+
+ final LockMode effectiveLockMode = lockOptions.getEffectiveLockMode( userAlias );
+ locks.setAliasSpecificLockMode( sqlAlias, effectiveLockMode );
+
if ( keyColumnNames != null ) {
keyColumnNames.put( sqlAlias, drivingPersister.getRootTableIdentifierColumnNames()
);
}
}
+
return dialect.applyLocksToSql( sql, locks, keyColumnNames );
}
Modified:
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java
===================================================================
---
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java 2010-01-31
21:50:23 UTC (rev 18674)
+++
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java 2010-02-01
19:42:16 UTC (rev 18675)
@@ -92,6 +92,7 @@
import org.hibernate.ejb.transaction.JoinableCMTTransaction;
import org.hibernate.ejb.util.CacheModeHelper;
import org.hibernate.ejb.util.ConfigurationHelper;
+import org.hibernate.ejb.util.LockModeTypeHelper;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.proxy.HibernateProxy;
@@ -851,52 +852,13 @@
@SuppressWarnings("deprecation")
private static LockModeType getLockModeType(LockMode lockMode) {
- if ( lockMode == LockMode.NONE )
- return LockModeType.NONE;
- else if ( lockMode == LockMode.OPTIMISTIC || lockMode == LockMode.READ )
- return LockModeType.OPTIMISTIC;
- else if ( lockMode == LockMode.OPTIMISTIC_FORCE_INCREMENT || lockMode == LockMode.WRITE
)
- return LockModeType.OPTIMISTIC_FORCE_INCREMENT;
- else if ( lockMode == LockMode.PESSIMISTIC_READ )
- return LockModeType.PESSIMISTIC_READ;
- else if ( lockMode == LockMode.PESSIMISTIC_WRITE
- || lockMode == LockMode.UPGRADE
- || lockMode == LockMode.UPGRADE_NOWAIT) //timeout of 0
- //TODO check that if we have UPGRADE_NOWAIT we have a timeout of zero?
- return LockModeType.PESSIMISTIC_WRITE;
- else if ( lockMode == LockMode.PESSIMISTIC_FORCE_INCREMENT
- || lockMode == LockMode.FORCE)
- return LockModeType.PESSIMISTIC_FORCE_INCREMENT;
- throw new AssertionFailure("unhandled lock mode " + lockMode );
+ //TODO check that if we have UPGRADE_NOWAIT we have a timeout of zero?
+ return LockModeTypeHelper.getLockModeType( lockMode );
}
private static LockMode getLockMode(LockModeType lockMode) {
- switch ( lockMode ) {
-
- case READ:
- case OPTIMISTIC:
- return LockMode.OPTIMISTIC;
-
- case OPTIMISTIC_FORCE_INCREMENT:
- case WRITE:
- return LockMode.OPTIMISTIC_FORCE_INCREMENT;
-
- case PESSIMISTIC_READ:
- return LockMode.PESSIMISTIC_READ;
-
- case PESSIMISTIC_WRITE:
- return LockMode.PESSIMISTIC_WRITE;
-
- case PESSIMISTIC_FORCE_INCREMENT:
- return LockMode.PESSIMISTIC_FORCE_INCREMENT;
-
- case NONE:
- return LockMode.NONE;
-
- default:
- throw new AssertionFailure( "Unknown LockModeType: " + lockMode );
- }
+ return LockModeTypeHelper.getLockMode( lockMode );
}
public boolean isTransactionInProgress() {
Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractQueryImpl.java
===================================================================
---
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractQueryImpl.java 2010-01-31
21:50:23 UTC (rev 18674)
+++
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractQueryImpl.java 2010-02-01
19:42:16 UTC (rev 18675)
@@ -40,6 +40,7 @@
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.HibernateException;
+import org.hibernate.LockMode;
import org.hibernate.TypeMismatchException;
import static org.hibernate.ejb.QueryHints.HINT_CACHEABLE;
import static org.hibernate.ejb.QueryHints.HINT_CACHE_MODE;
@@ -52,6 +53,7 @@
import org.hibernate.ejb.util.CacheModeHelper;
import org.hibernate.ejb.util.ConfigurationHelper;
+import org.hibernate.ejb.util.LockModeTypeHelper;
import org.hibernate.hql.QueryExecutionRequestException;
/**
@@ -189,6 +191,10 @@
protected abstract void applyFlushMode(FlushMode flushMode);
+ protected abstract boolean canApplyLockModes();
+
+ protected abstract void applyAliasSpecificLockMode(String alias, LockMode lockMode);
+
/**
* {@inheritDoc}
*/
@@ -247,10 +253,24 @@
CacheModeHelper.interpretCacheMode( storeMode, retrieveMode )
);
}
- /* TODO:
- else if ( "org.hibernate.lockMode".equals( hintName ) ) {
- query.setAliasLockMode( alias, lockMode );
- }*/
+ else if ( hintName.startsWith( AvailableSettings.ALIAS_SPECIFIC_LOCK_MODE ) ) {
+ if ( ! canApplyLockModes() ) {
+ skipped = true;
+ }
+ else {
+ // extract the alias
+ final String alias = hintName.substring(
AvailableSettings.ALIAS_SPECIFIC_LOCK_MODE.length() );
+ // determine the LockMode
+ try {
+ final LockMode lockMode = LockModeTypeHelper.interpretLockMode( value );
+ applyAliasSpecificLockMode( alias, lockMode );
+ }
+ catch ( Exception e ) {
+ log.info( "Unable to determine lock mode value : {} -> {}", hintName,
value );
+ skipped = true;
+ }
+ }
+ }
else {
skipped = true;
log.info( "Ignoring unrecognized query hint [" + hintName + "]"
);
Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AvailableSettings.java
===================================================================
---
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AvailableSettings.java 2010-01-31
21:50:23 UTC (rev 18674)
+++
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AvailableSettings.java 2010-02-01
19:42:16 UTC (rev 18675)
@@ -192,6 +192,20 @@
//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
+ * Query hint (aka {@link javax.persistence.Query#setHint}) for applying
+ * an alias specific lock mode (aka {@link org.hibernate.Query#setLockMode}).
+ * <p/>
+ * Either {@link org.hibernate.LockMode} or {@link javax.persistence.LockModeType}
+ * are accepted. Also the String names of either are accepted as well.
<tt>null</tt>
+ * is additionally accepted as meaning {@link org.hibernate.LockMode#NONE}.
+ * <p/>
+ * Usage is to concatenate this setting name and the alias name together, separated
+ * by a dot. For example<code>Query.setHint(
"org.hibernate.lockMode.a", someLockMode )</code>
+ * would apply <code>someLockMode</code> to the alias
<code>"a"</code>.
+ */
+ public static final String ALIAS_SPECIFIC_LOCK_MODE =
"org.hibernate.lockMode";
+
+ /**
* JAR autodetection artifacts class, hbm
*/
public static final String AUTODETECTION = "hibernate.archive.autodetection";
Modified:
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java
===================================================================
---
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java 2010-01-31
21:50:23 UTC (rev 18674)
+++
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java 2010-02-01
19:42:16 UTC (rev 18675)
@@ -107,7 +107,7 @@
public PersistenceException wrapStaleStateException(StaleStateException e);
/**
- * Convert from JPA-2 LockModeType & properties into LockOptions
+ * Convert from JPA 2 {@link LockModeType} & properties into {@link LockOptions}
*
* @param lockModeType is the requested lock type
* @param properties are the lock properties
Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/QueryImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/QueryImpl.java 2010-01-31
21:50:23 UTC (rev 18674)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/QueryImpl.java 2010-02-01
19:42:16 UTC (rev 18675)
@@ -50,10 +50,11 @@
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.HibernateException;
+import org.hibernate.LockMode;
import org.hibernate.QueryParameterException;
import org.hibernate.TypeMismatchException;
import org.hibernate.SQLQuery;
-import org.hibernate.LockOptions;
+import org.hibernate.ejb.util.LockModeTypeHelper;
import org.hibernate.engine.query.NamedParameterDescriptor;
import org.hibernate.engine.query.OrdinalParameterDescriptor;
import org.hibernate.hql.QueryExecutionRequestException;
@@ -217,6 +218,15 @@
query.setFlushMode( flushMode );
}
+ protected boolean canApplyLockModes() {
+ return org.hibernate.impl.QueryImpl.class.isInstance( query );
+ }
+
+ @Override
+ protected void applyAliasSpecificLockMode(String alias, LockMode lockMode) {
+ ( (org.hibernate.impl.QueryImpl) query ).getLockOptions().setAliasSpecificLockMode(
alias, lockMode );
+ }
+
/**
* {@inheritDoc}
*/
@@ -590,13 +600,16 @@
@SuppressWarnings({ "unchecked" })
public TypedQuery<X> setLockMode(javax.persistence.LockModeType lockModeType) {
-
if (! getEntityManager().isTransactionInProgress()) {
throw new TransactionRequiredException( "no transaction is in progress" );
}
-
+ if ( ! canApplyLockModes() ) {
+ throw new IllegalStateException( "Not a JPAQL/Criteria query" );
+ }
this.jpaLockMode = lockModeType;
- query.setLockOptions(getEntityManager().getLockRequest(lockModeType, null));
+ ( (org.hibernate.impl.QueryImpl) query ).getLockOptions().setLockMode(
+ LockModeTypeHelper.getLockMode( lockModeType )
+ );
return this;
}
Modified:
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/util/CacheModeHelper.java
===================================================================
---
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/util/CacheModeHelper.java 2010-01-31
21:50:23 UTC (rev 18674)
+++
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/util/CacheModeHelper.java 2010-02-01
19:42:16 UTC (rev 18675)
@@ -29,7 +29,8 @@
import org.hibernate.CacheMode;
/**
- * TODO : javadoc
+ * Helper to deal with {@link CacheMode} <-> {@link CacheRetrieveMode}/{@link
CacheStoreMode}
+ * conversions.
*
* @author Steve Ebersole
*/
Added:
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/util/LockModeTypeHelper.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/util/LockModeTypeHelper.java
(rev 0)
+++
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/util/LockModeTypeHelper.java 2010-02-01
19:42:16 UTC (rev 18675)
@@ -0,0 +1,119 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.ejb.util;
+
+import javax.persistence.LockModeType;
+
+import org.hibernate.AssertionFailure;
+import org.hibernate.LockMode;
+
+/**
+ * Helper to deal with {@link LockModeType} <-> {@link LockMode} conversions.
+ *
+ * @author Steve Ebersole
+ */
+public class LockModeTypeHelper {
+ public static LockModeType getLockModeType(LockMode lockMode) {
+ if ( lockMode == LockMode.NONE ) {
+ return LockModeType.NONE;
+ }
+ else if ( lockMode == LockMode.OPTIMISTIC || lockMode == LockMode.READ ) {
+ return LockModeType.OPTIMISTIC;
+ }
+ else if ( lockMode == LockMode.OPTIMISTIC_FORCE_INCREMENT || lockMode == LockMode.WRITE
) {
+ return LockModeType.OPTIMISTIC_FORCE_INCREMENT;
+ }
+ else if ( lockMode == LockMode.PESSIMISTIC_READ ) {
+ return LockModeType.PESSIMISTIC_READ;
+ }
+ else if ( lockMode == LockMode.PESSIMISTIC_WRITE
+ || lockMode == LockMode.UPGRADE
+ || lockMode == LockMode.UPGRADE_NOWAIT ) {
+ return LockModeType.PESSIMISTIC_WRITE;
+ }
+ else if ( lockMode == LockMode.PESSIMISTIC_FORCE_INCREMENT
+ || lockMode == LockMode.FORCE ) {
+ return LockModeType.PESSIMISTIC_FORCE_INCREMENT;
+ }
+ throw new AssertionFailure( "unhandled lock mode " + lockMode );
+ }
+
+
+ public static LockMode getLockMode(LockModeType lockMode) {
+ switch ( lockMode ) {
+ case READ:
+ case OPTIMISTIC: {
+ return LockMode.OPTIMISTIC;
+ }
+ case OPTIMISTIC_FORCE_INCREMENT:
+ case WRITE: {
+ return LockMode.OPTIMISTIC_FORCE_INCREMENT;
+ }
+ case PESSIMISTIC_READ: {
+ return LockMode.PESSIMISTIC_READ;
+ }
+ case PESSIMISTIC_WRITE: {
+ return LockMode.PESSIMISTIC_WRITE;
+ }
+ case PESSIMISTIC_FORCE_INCREMENT: {
+ return LockMode.PESSIMISTIC_FORCE_INCREMENT;
+ }
+ case NONE: {
+ return LockMode.NONE;
+ }
+ default: {
+ throw new AssertionFailure( "Unknown LockModeType: " + lockMode );
+ }
+ }
+ }
+
+ public static LockMode interpretLockMode(Object value) {
+ if ( value == null ) {
+ return LockMode.NONE;
+ }
+ if ( LockMode.class.isInstance( value ) ) {
+ return (LockMode) value;
+ }
+ else if ( LockModeType.class.isInstance( value ) ) {
+ return getLockMode( (LockModeType) value );
+ }
+ else if ( String.class.isInstance( value ) ) {
+ // first try LockMode name
+ LockMode lockMode = LockMode.parse( (String) value );
+ if ( lockMode == null ) {
+ try {
+ lockMode = getLockMode( LockModeType.valueOf( (String) value ) );
+ }
+ catch ( Exception ignore ) {
+ }
+ }
+ if ( lockMode != null ) {
+ return lockMode;
+ }
+ }
+
+ throw new IllegalArgumentException( "Unknown lock mode source : " + value );
+ }
+
+}
Modified:
core/trunk/testsuite/src/test/java/org/hibernate/test/dialect/unit/lockhint/AbstractLockHintTest.java
===================================================================
---
core/trunk/testsuite/src/test/java/org/hibernate/test/dialect/unit/lockhint/AbstractLockHintTest.java 2010-01-31
21:50:23 UTC (rev 18674)
+++
core/trunk/testsuite/src/test/java/org/hibernate/test/dialect/unit/lockhint/AbstractLockHintTest.java 2010-02-01
19:42:16 UTC (rev 18675)
@@ -56,7 +56,7 @@
public void verify() {
LockOptions lockOptions = new LockOptions(LockMode.UPGRADE);
- lockOptions.setAliasLockMode(LockMode.UPGRADE, aliasToLock);
+ lockOptions.setAliasSpecificLockMode( aliasToLock, LockMode.UPGRADE );
String actualProcessedSql = dialect.applyLocksToSql( rawSql, lockOptions,
Collections.EMPTY_MAP );
assertEquals( expectedProcessedSql, actualProcessedSql );
}