HHH-13561 Do not retrieve the same ActionQueue multiple times

This commit is contained in:
Sanne Grinovero 2019-08-11 21:18:34 +01:00
parent fdca4b2854
commit d4e1b7ffbc
4 changed files with 20 additions and 9 deletions

View File

@ -7,6 +7,7 @@
package org.hibernate.event.internal; package org.hibernate.event.internal;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.engine.spi.ActionQueue;
import org.hibernate.event.spi.DirtyCheckEvent; import org.hibernate.event.spi.DirtyCheckEvent;
import org.hibernate.event.spi.DirtyCheckEventListener; import org.hibernate.event.spi.DirtyCheckEventListener;
import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreLogging;
@ -29,11 +30,12 @@ public class DefaultDirtyCheckEventListener extends AbstractFlushingEventListene
* @throws HibernateException * @throws HibernateException
*/ */
public void onDirtyCheck(DirtyCheckEvent event) throws HibernateException { public void onDirtyCheck(DirtyCheckEvent event) throws HibernateException {
int oldSize = event.getSession().getActionQueue().numberOfCollectionRemovals(); final ActionQueue actionQueue = event.getSession().getActionQueue();
int oldSize = actionQueue.numberOfCollectionRemovals();
try { try {
flushEverythingToExecutions(event); flushEverythingToExecutions(event);
boolean wasNeeded = event.getSession().getActionQueue().hasAnyQueuedActions(); boolean wasNeeded = actionQueue.hasAnyQueuedActions();
if ( wasNeeded ) { if ( wasNeeded ) {
LOG.debug( "Session dirty" ); LOG.debug( "Session dirty" );
} }
@ -43,7 +45,7 @@ public class DefaultDirtyCheckEventListener extends AbstractFlushingEventListene
event.setDirty( wasNeeded ); event.setDirty( wasNeeded );
} }
finally { finally {
event.getSession().getActionQueue().clearFromFlushNeededCheck( oldSize ); actionQueue.clearFromFlushNeededCheck( oldSize );
} }
} }
} }

View File

@ -20,15 +20,18 @@ import org.hibernate.cache.spi.access.EntityDataAccess;
import org.hibernate.cache.spi.access.SoftLock; import org.hibernate.cache.spi.access.SoftLock;
import org.hibernate.engine.internal.Cascade; import org.hibernate.engine.internal.Cascade;
import org.hibernate.engine.internal.CascadePoint; import org.hibernate.engine.internal.CascadePoint;
import org.hibernate.engine.spi.ActionQueue;
import org.hibernate.engine.spi.CascadingActions; import org.hibernate.engine.spi.CascadingActions;
import org.hibernate.engine.spi.EntityEntry; import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.EntityKey; import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.event.spi.EventSource; import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.RefreshEvent; import org.hibernate.event.spi.RefreshEvent;
import org.hibernate.event.spi.RefreshEventListener; import org.hibernate.event.spi.RefreshEventListener;
import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.metamodel.spi.MetamodelImplementor;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.pretty.MessageHelper; import org.hibernate.pretty.MessageHelper;
@ -239,20 +242,23 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
private void evictCachedCollections(Type[] types, Serializable id, EventSource source) private void evictCachedCollections(Type[] types, Serializable id, EventSource source)
throws HibernateException { throws HibernateException {
final ActionQueue actionQueue = source.getActionQueue();
final SessionFactoryImplementor factory = source.getFactory();
final MetamodelImplementor metamodel = factory.getMetamodel();
for ( Type type : types ) { for ( Type type : types ) {
if ( type.isCollectionType() ) { if ( type.isCollectionType() ) {
CollectionPersister collectionPersister = source.getFactory().getMetamodel().collectionPersister( ( (CollectionType) type ).getRole() ); CollectionPersister collectionPersister = metamodel.collectionPersister( ( (CollectionType) type ).getRole() );
if ( collectionPersister.hasCache() ) { if ( collectionPersister.hasCache() ) {
final CollectionDataAccess cache = collectionPersister.getCacheAccessStrategy(); final CollectionDataAccess cache = collectionPersister.getCacheAccessStrategy();
final Object ck = cache.generateCacheKey( final Object ck = cache.generateCacheKey(
id, id,
collectionPersister, collectionPersister,
source.getFactory(), factory,
source.getTenantIdentifier() source.getTenantIdentifier()
); );
final SoftLock lock = cache.lockItem( source, ck, null ); final SoftLock lock = cache.lockItem( source, ck, null );
cache.remove( source, ck ); cache.remove( source, ck );
source.getActionQueue().registerProcess( (success, session) -> cache.unlockItem( session, ck, lock ) ); actionQueue.registerProcess( (success, session) -> cache.unlockItem( session, ck, lock ) );
} }
} }
else if ( type.isComponentType() ) { else if ( type.isComponentType() ) {

View File

@ -422,7 +422,8 @@ public final class SessionImpl
return super.shouldCloseJdbcCoordinatorOnClose( isTransactionCoordinatorShared ); return super.shouldCloseJdbcCoordinatorOnClose( isTransactionCoordinatorShared );
} }
if ( getActionQueue().hasBeforeTransactionActions() || getActionQueue().hasAfterTransactionActions() ) { final ActionQueue actionQueue = getActionQueue();
if ( actionQueue.hasBeforeTransactionActions() || actionQueue.hasAfterTransactionActions() ) {
log.warn( log.warn(
"On close, shared Session had before/after transaction actions that have not yet been processed" "On close, shared Session had before/after transaction actions that have not yet been processed"
); );

View File

@ -20,6 +20,7 @@ import org.hibernate.Session;
import org.hibernate.action.spi.AfterTransactionCompletionProcess; import org.hibernate.action.spi.AfterTransactionCompletionProcess;
import org.hibernate.action.spi.BeforeTransactionCompletionProcess; import org.hibernate.action.spi.BeforeTransactionCompletionProcess;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.ActionQueue;
import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.junit.Test; import org.junit.Test;
@ -71,8 +72,9 @@ public class AfterCompletionTest extends BaseNonConfigCoreFunctionalTestCase {
// The before causes the original thread to wait until Reaper aborts the transaction // The before causes the original thread to wait until Reaper aborts the transaction
// The after tracks whether it is invoked since this test is to guarantee it is called // The after tracks whether it is invoked since this test is to guarantee it is called
final SessionImplementor sessionImplementor = (SessionImplementor) session; final SessionImplementor sessionImplementor = (SessionImplementor) session;
sessionImplementor.getActionQueue().registerProcess( new AfterCallbackCompletionHandler() ); final ActionQueue actionQueue = sessionImplementor.getActionQueue();
sessionImplementor.getActionQueue().registerProcess( new BeforeCallbackCompletionHandler() ); actionQueue.registerProcess( new AfterCallbackCompletionHandler() );
actionQueue.registerProcess( new BeforeCallbackCompletionHandler() );
TestingJtaPlatformImpl.transactionManager().commit(); TestingJtaPlatformImpl.transactionManager().commit();
} }