HHH-4661 - Properly propagate Query.setLockMode to Hibernate Core
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@18682 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
889470af88
commit
1591e6dc03
|
@ -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 @@ import org.hibernate.persister.entity.EntityPersister;
|
|||
*
|
||||
* @author Scott Marlow
|
||||
*/
|
||||
public class EntityIncrementVersionProcess implements BeforeTransactionCompletionProcess
|
||||
{
|
||||
public class EntityIncrementVersionProcess implements BeforeTransactionCompletionProcess {
|
||||
private final Object object;
|
||||
private final EntityEntry entry;
|
||||
|
||||
|
|
|
@ -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.engine.SessionImplementor;
|
||||
import org.hibernate.engine.EntityEntry;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.OptimisticLockException;
|
||||
import org.hibernate.engine.EntityEntry;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
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 class EntityVerifyVersionProcess implements BeforeTransactionCompletionPr
|
|||
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"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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.HibernateException;
|
|||
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 @@ import org.slf4j.LoggerFactory;
|
|||
* <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 @@ public class OptimisticForceIncrementLockingStrategy implements LockingStrategy
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @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() {
|
||||
|
|
|
@ -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.HibernateException;
|
|||
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 @@ public class PessimisticForceIncrementLockingStrategy implements LockingStrategy
|
|||
* 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 @@ public class PessimisticForceIncrementLockingStrategy implements LockingStrategy
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
|
|
|
@ -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() );
|
||||
|
|
|
@ -136,6 +136,27 @@ public class FromClause extends HqlSqlWalkerNode implements HqlSqlTokenTypes, Di
|
|||
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() ) {
|
||||
|
|
|
@ -643,10 +643,15 @@ public abstract class Loader {
|
|||
}
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
|
|
|
@ -39,6 +39,7 @@ import org.hibernate.QueryException;
|
|||
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 @@ public class QueryLoader extends BasicLoader {
|
|||
* @param lockOptions a collection of lock modes specified dynamically via the Query interface
|
||||
*/
|
||||
protected LockMode[] getLockModes(LockOptions lockOptions) {
|
||||
|
||||
if ( lockOptions == null ||
|
||||
lockOptions.getAliasLockCount() == 0 ) {
|
||||
if ( lockOptions == null ) {
|
||||
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;
|
||||
}
|
||||
return lockModesArray;
|
||||
if ( lockOptions.getAliasLockCount() == 0
|
||||
&& ( lockOptions.getLockMode() == null || LockMode.NONE.equals( lockOptions.getLockMode() ) ) ) {
|
||||
return defaultLockModes;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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 @@ public class QueryLoader extends BasicLoader {
|
|||
// 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 @@ public class QueryLoader extends BasicLoader {
|
|||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
|
|
@ -259,7 +259,7 @@ public abstract class AbstractQueryImpl<X> implements TypedQuery<X> {
|
|||
}
|
||||
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 );
|
||||
|
|
|
@ -15,6 +15,13 @@ public class Lock {
|
|||
private Integer version;
|
||||
private String name;
|
||||
|
||||
public Lock() {
|
||||
}
|
||||
|
||||
public Lock(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
public Integer getId() {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue