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;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.ActionQueue;
import org.hibernate.event.spi.DirtyCheckEvent;
import org.hibernate.event.spi.DirtyCheckEventListener;
import org.hibernate.internal.CoreLogging;
@ -29,11 +30,12 @@ public class DefaultDirtyCheckEventListener extends AbstractFlushingEventListene
* @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 {
flushEverythingToExecutions(event);
boolean wasNeeded = event.getSession().getActionQueue().hasAnyQueuedActions();
boolean wasNeeded = actionQueue.hasAnyQueuedActions();
if ( wasNeeded ) {
LOG.debug( "Session dirty" );
}
@ -43,7 +45,7 @@ public class DefaultDirtyCheckEventListener extends AbstractFlushingEventListene
event.setDirty( wasNeeded );
}
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.engine.internal.Cascade;
import org.hibernate.engine.internal.CascadePoint;
import org.hibernate.engine.spi.ActionQueue;
import org.hibernate.engine.spi.CascadingActions;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.RefreshEvent;
import org.hibernate.event.spi.RefreshEventListener;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.metamodel.spi.MetamodelImplementor;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.pretty.MessageHelper;
@ -239,20 +242,23 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
private void evictCachedCollections(Type[] types, Serializable id, EventSource source)
throws HibernateException {
final ActionQueue actionQueue = source.getActionQueue();
final SessionFactoryImplementor factory = source.getFactory();
final MetamodelImplementor metamodel = factory.getMetamodel();
for ( Type type : types ) {
if ( type.isCollectionType() ) {
CollectionPersister collectionPersister = source.getFactory().getMetamodel().collectionPersister( ( (CollectionType) type ).getRole() );
CollectionPersister collectionPersister = metamodel.collectionPersister( ( (CollectionType) type ).getRole() );
if ( collectionPersister.hasCache() ) {
final CollectionDataAccess cache = collectionPersister.getCacheAccessStrategy();
final Object ck = cache.generateCacheKey(
id,
collectionPersister,
source.getFactory(),
factory,
source.getTenantIdentifier()
);
final SoftLock lock = cache.lockItem( source, ck, null );
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() ) {

View File

@ -422,7 +422,8 @@ public final class SessionImpl
return super.shouldCloseJdbcCoordinatorOnClose( isTransactionCoordinatorShared );
}
if ( getActionQueue().hasBeforeTransactionActions() || getActionQueue().hasAfterTransactionActions() ) {
final ActionQueue actionQueue = getActionQueue();
if ( actionQueue.hasBeforeTransactionActions() || actionQueue.hasAfterTransactionActions() ) {
log.warn(
"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.BeforeTransactionCompletionProcess;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.ActionQueue;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
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 after tracks whether it is invoked since this test is to guarantee it is called
final SessionImplementor sessionImplementor = (SessionImplementor) session;
sessionImplementor.getActionQueue().registerProcess( new AfterCallbackCompletionHandler() );
sessionImplementor.getActionQueue().registerProcess( new BeforeCallbackCompletionHandler() );
final ActionQueue actionQueue = sessionImplementor.getActionQueue();
actionQueue.registerProcess( new AfterCallbackCompletionHandler() );
actionQueue.registerProcess( new BeforeCallbackCompletionHandler() );
TestingJtaPlatformImpl.transactionManager().commit();
}