HHH-13448 Avoid retrieving PRE_LOAD and POST_LOAD Event listeners within the inner loops of TwoPhaseLoad

This commit is contained in:
Sanne Grinovero 2019-07-01 20:08:02 +01:00
parent 9e9154cb5e
commit 71b22a3258
3 changed files with 125 additions and 26 deletions

View File

@ -103,6 +103,34 @@ public static void postHydrate(
} }
} }
/**
* @deprecated This method will be removed. Use {@link #initializeEntity(Object, boolean, SharedSessionContractImplementor, PreLoadEvent, Iterable)} instead.
*
* @param entity The entity being loaded
* @param readOnly Is the entity being loaded as read-only
* @param session The Session
* @param preLoadEvent The (re-used) pre-load event
*/
@Deprecated
public static void initializeEntity(
final Object entity,
final boolean readOnly,
final SharedSessionContractImplementor session,
final PreLoadEvent preLoadEvent) {
final PersistenceContext persistenceContext = session.getPersistenceContext();
final EntityEntry entityEntry = persistenceContext.getEntry( entity );
if ( entityEntry == null ) {
throw new AssertionFailure( "possible non-threadsafe access to the session" );
}
final EventListenerGroup<PreLoadEventListener> listenerGroup = session
.getFactory()
.getServiceRegistry()
.getService( EventListenerRegistry.class )
.getEventListenerGroup( EventType.PRE_LOAD );
final Iterable<PreLoadEventListener> listeners = listenerGroup.listeners();
doInitializeEntity( entity, entityEntry, readOnly, session, preLoadEvent, listeners );
}
/** /**
* Perform the second step of 2-phase load. Fully initialize the entity * Perform the second step of 2-phase load. Fully initialize the entity
* instance. * instance.
@ -115,18 +143,20 @@ public static void postHydrate(
* @param readOnly Is the entity being loaded as read-only * @param readOnly Is the entity being loaded as read-only
* @param session The Session * @param session The Session
* @param preLoadEvent The (re-used) pre-load event * @param preLoadEvent The (re-used) pre-load event
* @param preLoadEventListeners the pre-load event listeners
*/ */
public static void initializeEntity( public static void initializeEntity(
final Object entity, final Object entity,
final boolean readOnly, final boolean readOnly,
final SharedSessionContractImplementor session, final SharedSessionContractImplementor session,
final PreLoadEvent preLoadEvent) { final PreLoadEvent preLoadEvent,
final Iterable<PreLoadEventListener> preLoadEventListeners) {
final PersistenceContext persistenceContext = session.getPersistenceContext(); final PersistenceContext persistenceContext = session.getPersistenceContext();
final EntityEntry entityEntry = persistenceContext.getEntry( entity ); final EntityEntry entityEntry = persistenceContext.getEntry( entity );
if ( entityEntry == null ) { if ( entityEntry == null ) {
throw new AssertionFailure( "possible non-threadsafe access to the session" ); throw new AssertionFailure( "possible non-threadsafe access to the session" );
} }
doInitializeEntity( entity, entityEntry, readOnly, session, preLoadEvent ); doInitializeEntity( entity, entityEntry, readOnly, session, preLoadEvent, preLoadEventListeners );
} }
private static void doInitializeEntity( private static void doInitializeEntity(
@ -134,7 +164,8 @@ private static void doInitializeEntity(
final EntityEntry entityEntry, final EntityEntry entityEntry,
final boolean readOnly, final boolean readOnly,
final SharedSessionContractImplementor session, final SharedSessionContractImplementor session,
final PreLoadEvent preLoadEvent) throws HibernateException { final PreLoadEvent preLoadEvent,
final Iterable<PreLoadEventListener> preLoadEventListeners) throws HibernateException {
final PersistenceContext persistenceContext = session.getPersistenceContext(); final PersistenceContext persistenceContext = session.getPersistenceContext();
final EntityPersister persister = entityEntry.getPersister(); final EntityPersister persister = entityEntry.getPersister();
final Serializable id = entityEntry.getId(); final Serializable id = entityEntry.getId();
@ -176,13 +207,7 @@ else if ( value != PropertyAccessStrategyBackRefImpl.UNKNOWN ) {
//Must occur after resolving identifiers! //Must occur after resolving identifiers!
if ( session.isEventSource() ) { if ( session.isEventSource() ) {
preLoadEvent.setEntity( entity ).setState( hydratedState ).setId( id ).setPersister( persister ); preLoadEvent.setEntity( entity ).setState( hydratedState ).setId( id ).setPersister( persister );
for ( PreLoadEventListener listener : preLoadEventListeners ) {
final EventListenerGroup<PreLoadEventListener> listenerGroup = session
.getFactory()
.getServiceRegistry()
.getService( EventListenerRegistry.class )
.getEventListenerGroup( EventType.PRE_LOAD );
for ( PreLoadEventListener listener : listenerGroup.listeners() ) {
listener.onPreLoad( preLoadEvent ); listener.onPreLoad( preLoadEvent );
} }
} }
@ -361,11 +386,13 @@ private static Boolean isEagerFetchProfile(SharedSessionContractImplementor sess
* @param entity The entity * @param entity The entity
* @param session The Session * @param session The Session
* @param postLoadEvent The (re-used) post-load event * @param postLoadEvent The (re-used) post-load event
* @param postLoadEventListeners thet post-load eventListeners
*/ */
public static void postLoad( public static void postLoad(
final Object entity, final Object entity,
final SharedSessionContractImplementor session, final SharedSessionContractImplementor session,
final PostLoadEvent postLoadEvent) { final PostLoadEvent postLoadEvent,
final Iterable<PostLoadEventListener> postLoadEventListeners) {
if ( session.isEventSource() ) { if ( session.isEventSource() ) {
final PersistenceContext persistenceContext final PersistenceContext persistenceContext
@ -374,16 +401,31 @@ public static void postLoad(
postLoadEvent.setEntity( entity ).setId( entityEntry.getId() ).setPersister( entityEntry.getPersister() ); postLoadEvent.setEntity( entity ).setId( entityEntry.getId() ).setPersister( entityEntry.getPersister() );
final EventListenerGroup<PostLoadEventListener> listenerGroup = session.getFactory() for ( PostLoadEventListener listener : postLoadEventListeners ) {
.getServiceRegistry()
.getService( EventListenerRegistry.class )
.getEventListenerGroup( EventType.POST_LOAD );
for ( PostLoadEventListener listener : listenerGroup.listeners() ) {
listener.onPostLoad( postLoadEvent ); listener.onPostLoad( postLoadEvent );
} }
} }
} }
/**
* This method will be removed.
* @deprecated Use {@link #postLoad(Object, SharedSessionContractImplementor, PostLoadEvent, Iterable)}
* instead.
*/
@Deprecated
public static void postLoad(
final Object entity,
final SharedSessionContractImplementor session,
final PostLoadEvent postLoadEvent) {
final EventListenerGroup<PostLoadEventListener> listenerGroup = session.getFactory()
.getServiceRegistry()
.getService( EventListenerRegistry.class )
.getEventListenerGroup( EventType.POST_LOAD );
postLoad( entity, session, postLoadEvent, listenerGroup.listeners() );
}
private static boolean useMinimalPuts(SharedSessionContractImplementor session, EntityEntry entityEntry) { private static boolean useMinimalPuts(SharedSessionContractImplementor session, EntityEntry entityEntry) {
if ( session.getFactory().getSessionFactoryOptions().isMinimalPutsEnabled() ) { if ( session.getFactory().getSessionFactoryOptions().isMinimalPutsEnabled() ) {
return session.getCacheMode() != CacheMode.REFRESH; return session.getCacheMode() != CacheMode.REFRESH;

View File

@ -59,9 +59,14 @@
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.engine.spi.SubselectFetch; import org.hibernate.engine.spi.SubselectFetch;
import org.hibernate.engine.spi.TypedValue; import org.hibernate.engine.spi.TypedValue;
import org.hibernate.event.service.spi.EventListenerGroup;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventSource; import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.PostLoadEvent; import org.hibernate.event.spi.PostLoadEvent;
import org.hibernate.event.spi.PostLoadEventListener;
import org.hibernate.event.spi.PreLoadEvent; import org.hibernate.event.spi.PreLoadEvent;
import org.hibernate.event.spi.PreLoadEventListener;
import org.hibernate.hql.internal.HolderInstantiator; import org.hibernate.hql.internal.HolderInstantiator;
import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
@ -1154,8 +1159,19 @@ private void initializeEntitiesAndCollections(
if ( hydratedObjects != null ) { if ( hydratedObjects != null ) {
int hydratedObjectsSize = hydratedObjects.size(); int hydratedObjectsSize = hydratedObjects.size();
LOG.tracev( "Total objects hydrated: {0}", hydratedObjectsSize ); LOG.tracev( "Total objects hydrated: {0}", hydratedObjectsSize );
for ( Object hydratedObject : hydratedObjects ) {
TwoPhaseLoad.initializeEntity( hydratedObject, readOnly, session, pre ); if ( hydratedObjectsSize != 0 ) {
final Iterable<PreLoadEventListener> listeners = session
.getFactory()
.getServiceRegistry()
.getService( EventListenerRegistry.class )
.getEventListenerGroup( EventType.PRE_LOAD )
.listeners();
for ( Object hydratedObject : hydratedObjects ) {
TwoPhaseLoad.initializeEntity( hydratedObject, readOnly, session, pre, listeners );
}
} }
} }
@ -1175,9 +1191,22 @@ private void initializeEntitiesAndCollections(
// split off from initializeEntity. It *must* occur after // split off from initializeEntity. It *must* occur after
// endCollectionLoad to ensure the collection is in the // endCollectionLoad to ensure the collection is in the
// persistence context. // persistence context.
if ( hydratedObjects != null ) { if ( hydratedObjects != null && hydratedObjects.size() > 0 ) {
final Iterable<PostLoadEventListener> postLoadEventListeners;
if ( session.isEventSource() ) {
final EventListenerGroup<PostLoadEventListener> listenerGroup = session.getFactory()
.getServiceRegistry()
.getService( EventListenerRegistry.class )
.getEventListenerGroup( EventType.POST_LOAD );
postLoadEventListeners = listenerGroup.listeners();
}
else {
postLoadEventListeners = Collections.emptyList();
}
for ( Object hydratedObject : hydratedObjects ) { for ( Object hydratedObject : hydratedObjects ) {
TwoPhaseLoad.postLoad( hydratedObject, session, post ); TwoPhaseLoad.postLoad( hydratedObject, session, post, postLoadEventListeners );
if ( afterLoadActions != null ) { if ( afterLoadActions != null ) {
for ( AfterLoadAction afterLoadAction : afterLoadActions ) { for ( AfterLoadAction afterLoadAction : afterLoadActions ) {
final EntityEntry entityEntry = session.getPersistenceContext().getEntry( hydratedObject ); final EntityEntry entityEntry = session.getPersistenceContext().getEntry( hydratedObject );

View File

@ -15,9 +15,15 @@
import java.util.Map; import java.util.Map;
import org.hibernate.engine.internal.TwoPhaseLoad; import org.hibernate.engine.internal.TwoPhaseLoad;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.event.service.spi.EventListenerGroup;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventSource; import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.PostLoadEvent; import org.hibernate.event.spi.PostLoadEvent;
import org.hibernate.event.spi.PostLoadEventListener;
import org.hibernate.event.spi.PreLoadEvent; import org.hibernate.event.spi.PreLoadEvent;
import org.hibernate.event.spi.PreLoadEventListener;
import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.loader.plan.exec.process.spi.CollectionReferenceInitializer; import org.hibernate.loader.plan.exec.process.spi.CollectionReferenceInitializer;
@ -230,16 +236,25 @@ private void performTwoPhaseLoad(
: hydratedEntityRegistrations.size(); : hydratedEntityRegistrations.size();
log.tracev( "Total objects hydrated: {0}", numberOfHydratedObjects ); log.tracev( "Total objects hydrated: {0}", numberOfHydratedObjects );
if ( hydratedEntityRegistrations == null ) { if ( numberOfHydratedObjects == 0 ) {
return; return;
} }
final SharedSessionContractImplementor session = context.getSession();
final Iterable<PreLoadEventListener> listeners = session
.getFactory()
.getServiceRegistry()
.getService( EventListenerRegistry.class )
.getEventListenerGroup( EventType.PRE_LOAD )
.listeners();
for ( HydratedEntityRegistration registration : hydratedEntityRegistrations ) { for ( HydratedEntityRegistration registration : hydratedEntityRegistrations ) {
TwoPhaseLoad.initializeEntity( TwoPhaseLoad.initializeEntity(
registration.getInstance(), registration.getInstance(),
context.isReadOnly(), context.isReadOnly(),
context.getSession(), session,
preLoadEvent preLoadEvent,
listeners
); );
} }
} }
@ -259,16 +274,29 @@ private void postLoad(
// split off from initializeEntity. It *must* occur after // split off from initializeEntity. It *must* occur after
// endCollectionLoad to ensure the collection is in the // endCollectionLoad to ensure the collection is in the
// persistence context. // persistence context.
if ( hydratedEntityRegistrations == null ) { if ( hydratedEntityRegistrations == null || hydratedEntityRegistrations.size() == 0 ) {
return; return;
} }
final SharedSessionContractImplementor session = context.getSession();
final Iterable<PostLoadEventListener> postLoadEventListeners;
if ( session.isEventSource() ) {
final EventListenerGroup<PostLoadEventListener> listenerGroup = session.getFactory()
.getServiceRegistry()
.getService( EventListenerRegistry.class )
.getEventListenerGroup( EventType.POST_LOAD );
postLoadEventListeners = listenerGroup.listeners();
}
else {
postLoadEventListeners = Collections.emptyList();
}
for ( HydratedEntityRegistration registration : hydratedEntityRegistrations ) { for ( HydratedEntityRegistration registration : hydratedEntityRegistrations ) {
TwoPhaseLoad.postLoad( registration.getInstance(), context.getSession(), postLoadEvent ); TwoPhaseLoad.postLoad( registration.getInstance(), session, postLoadEvent, postLoadEventListeners );
if ( afterLoadActionList != null ) { if ( afterLoadActionList != null ) {
for ( AfterLoadAction afterLoadAction : afterLoadActionList ) { for ( AfterLoadAction afterLoadAction : afterLoadActionList ) {
afterLoadAction.afterLoad( afterLoadAction.afterLoad(
context.getSession(), session,
registration.getInstance(), registration.getInstance(),
(Loadable) registration.getEntityReference().getEntityPersister() (Loadable) registration.getEntityReference().getEntityPersister()
); );