HHH-14447 Add missing EventGroupListeners into FastSessionService and take advantage of them

This commit is contained in:
Sanne Grinovero 2021-01-25 21:25:39 +00:00 committed by Andrea Boriero
parent 14e181806f
commit 81a9b87ec1
14 changed files with 264 additions and 233 deletions

View File

@ -20,6 +20,7 @@
import org.hibernate.event.service.spi.EventListenerRegistry; 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.EventType;
import org.hibernate.internal.FastSessionServices;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.pretty.MessageHelper; import org.hibernate.pretty.MessageHelper;
@ -184,6 +185,11 @@ public void doAfterTransactionCompletion(boolean success, SharedSessionContractI
} }
} }
/**
* @deprecated This will be removed as it's not very efficient. If you need access to EventListenerGroup(s),
* use the direct references from {@link #getFastSessionServices()}.
*/
@Deprecated
protected <T> EventListenerGroup<T> listenerGroup(EventType<T> eventType) { protected <T> EventListenerGroup<T> listenerGroup(EventType<T> eventType) {
return getSession() return getSession()
.getFactory() .getFactory()
@ -195,4 +201,13 @@ protected <T> EventListenerGroup<T> listenerGroup(EventType<T> eventType) {
protected EventSource eventSource() { protected EventSource eventSource() {
return (EventSource) getSession(); return (EventSource) getSession();
} }
/**
* Convenience method for all subclasses.
* @return the {@link FastSessionServices} instance from the SessionFactory.
*/
protected FastSessionServices getFastSessionServices() {
return session.getFactory().getFastSessionServices();
}
} }

View File

@ -11,8 +11,6 @@
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.event.service.spi.EventListenerGroup;
import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.PostCollectionRecreateEvent; import org.hibernate.event.spi.PostCollectionRecreateEvent;
import org.hibernate.event.spi.PostCollectionRecreateEventListener; import org.hibernate.event.spi.PostCollectionRecreateEventListener;
import org.hibernate.event.spi.PreCollectionRecreateEvent; import org.hibernate.event.spi.PreCollectionRecreateEvent;
@ -61,24 +59,22 @@ public void execute() throws HibernateException {
} }
private void preRecreate() { private void preRecreate() {
final EventListenerGroup<PreCollectionRecreateEventListener> listenerGroup = listenerGroup( EventType.PRE_COLLECTION_RECREATE ); getFastSessionServices()
if ( listenerGroup.isEmpty() ) { .eventListenerGroup_PRE_COLLECTION_RECREATE
return; .fireLazyEventOnEachListener( this::newPreCollectionRecreateEvent, PreCollectionRecreateEventListener::onPreRecreateCollection );
} }
final PreCollectionRecreateEvent event = new PreCollectionRecreateEvent( getPersister(), getCollection(), eventSource() );
for ( PreCollectionRecreateEventListener listener : listenerGroup.listeners() ) { private PreCollectionRecreateEvent newPreCollectionRecreateEvent() {
listener.onPreRecreateCollection( event ); return new PreCollectionRecreateEvent( getPersister(), getCollection(), eventSource() );
}
} }
private void postRecreate() { private void postRecreate() {
final EventListenerGroup<PostCollectionRecreateEventListener> listenerGroup = listenerGroup( EventType.POST_COLLECTION_RECREATE ); getFastSessionServices()
if ( listenerGroup.isEmpty() ) { .eventListenerGroup_POST_COLLECTION_RECREATE
return; .fireLazyEventOnEachListener( this::newPostCollectionRecreateEvent, PostCollectionRecreateEventListener::onPostRecreateCollection );
} }
final PostCollectionRecreateEvent event = new PostCollectionRecreateEvent( getPersister(), getCollection(), eventSource() );
for ( PostCollectionRecreateEventListener listener : listenerGroup.listeners() ) { private PostCollectionRecreateEvent newPostCollectionRecreateEvent() {
listener.onPostRecreateCollection( event ); return new PostCollectionRecreateEvent( getPersister(), getCollection(), eventSource() );
}
} }
} }

View File

@ -114,34 +114,33 @@ public void execute() throws HibernateException {
} }
private void preRemove() { private void preRemove() {
final EventListenerGroup<PreCollectionRemoveEventListener> listenerGroup = listenerGroup( EventType.PRE_COLLECTION_REMOVE ); getFastSessionServices()
if ( listenerGroup.isEmpty() ) { .eventListenerGroup_PRE_COLLECTION_REMOVE
return; .fireLazyEventOnEachListener( this::newPreCollectionRemoveEvent, PreCollectionRemoveEventListener::onPreRemoveCollection );
} }
final PreCollectionRemoveEvent event = new PreCollectionRemoveEvent(
private PreCollectionRemoveEvent newPreCollectionRemoveEvent() {
return new PreCollectionRemoveEvent(
getPersister(), getPersister(),
getCollection(), getCollection(),
eventSource(), eventSource(),
affectedOwner affectedOwner
); );
for ( PreCollectionRemoveEventListener listener : listenerGroup.listeners() ) {
listener.onPreRemoveCollection( event );
}
} }
private void postRemove() { private void postRemove() {
final EventListenerGroup<PostCollectionRemoveEventListener> listenerGroup = listenerGroup( EventType.POST_COLLECTION_REMOVE ); getFastSessionServices()
if ( listenerGroup.isEmpty() ) { .eventListenerGroup_POST_COLLECTION_REMOVE
return; .fireLazyEventOnEachListener( this::newPostCollectionRemoveEvent, PostCollectionRemoveEventListener::onPostRemoveCollection );
} }
final PostCollectionRemoveEvent event = new PostCollectionRemoveEvent(
private PostCollectionRemoveEvent newPostCollectionRemoveEvent() {
return new PostCollectionRemoveEvent(
getPersister(), getPersister(),
getCollection(), getCollection(),
eventSource(), eventSource(),
affectedOwner affectedOwner
); );
for ( PostCollectionRemoveEventListener listener : listenerGroup.listeners() ) {
listener.onPostRemoveCollection( event );
}
} }
} }

View File

@ -100,32 +100,31 @@ else if ( collection.needsRecreate( persister ) ) {
} }
private void preUpdate() { private void preUpdate() {
final EventListenerGroup<PreCollectionUpdateEventListener> listenerGroup = listenerGroup( EventType.PRE_COLLECTION_UPDATE ); getFastSessionServices()
if ( listenerGroup.isEmpty() ) { .eventListenerGroup_PRE_COLLECTION_UPDATE
return; .fireLazyEventOnEachListener( this::newPreCollectionUpdateEvent, PreCollectionUpdateEventListener::onPreUpdateCollection );
} }
final PreCollectionUpdateEvent event = new PreCollectionUpdateEvent(
private PreCollectionUpdateEvent newPreCollectionUpdateEvent() {
return new PreCollectionUpdateEvent(
getPersister(), getPersister(),
getCollection(), getCollection(),
eventSource() eventSource()
); );
for ( PreCollectionUpdateEventListener listener : listenerGroup.listeners() ) {
listener.onPreUpdateCollection( event );
}
} }
private void postUpdate() { private void postUpdate() {
final EventListenerGroup<PostCollectionUpdateEventListener> listenerGroup = listenerGroup( EventType.POST_COLLECTION_UPDATE ); getFastSessionServices()
if ( listenerGroup.isEmpty() ) { .eventListenerGroup_POST_COLLECTION_UPDATE
return; .fireLazyEventOnEachListener( this::newPostCollectionUpdateEvent, PostCollectionUpdateEventListener::onPostUpdateCollection );
} }
final PostCollectionUpdateEvent event = new PostCollectionUpdateEvent(
private PostCollectionUpdateEvent newPostCollectionUpdateEvent() {
return new PostCollectionUpdateEvent(
getPersister(), getPersister(),
getCollection(), getCollection(),
eventSource() eventSource()
); );
for ( PostCollectionUpdateEventListener listener : listenerGroup.listeners() ) {
listener.onPostUpdateCollection( event );
}
} }
} }

View File

@ -18,12 +18,11 @@
import org.hibernate.event.service.spi.EventListenerRegistry; 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.EventType;
import org.hibernate.internal.FastSessionServices;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.pretty.MessageHelper; import org.hibernate.pretty.MessageHelper;
import org.jboss.logging.Logger;
/** /**
* Base class for actions relating to insert/update/delete of an entity * Base class for actions relating to insert/update/delete of an entity
* instance. * instance.
@ -32,7 +31,6 @@
*/ */
public abstract class EntityAction public abstract class EntityAction
implements Executable, Serializable, Comparable, AfterTransactionCompletionProcess { implements Executable, Serializable, Comparable, AfterTransactionCompletionProcess {
private static final Logger LOG = Logger.getLogger(EntityAction.class);
private final String entityName; private final String entityName;
private final Serializable id; private final Serializable id;
@ -189,6 +187,11 @@ public void afterDeserialize(SharedSessionContractImplementor session) {
} }
} }
/**
* @deprecated This will be removed as it's not very efficient. If you need access to EventListenerGroup(s),
* use the direct references from {@link #getFastSessionServices()}.
*/
@Deprecated
protected <T> EventListenerGroup<T> listenerGroup(EventType<T> eventType) { protected <T> EventListenerGroup<T> listenerGroup(EventType<T> eventType) {
return getSession() return getSession()
.getFactory() .getFactory()
@ -200,4 +203,13 @@ protected <T> EventListenerGroup<T> listenerGroup(EventType<T> eventType) {
protected EventSource eventSource() { protected EventSource eventSource() {
return (EventSource) getSession(); return (EventSource) getSession();
} }
/**
* Convenience method for all subclasses.
* @return the {@link FastSessionServices} instance from the SessionFactory.
*/
protected FastSessionServices getFastSessionServices() {
return session.getFactory().getFastSessionServices();
}
} }

View File

@ -17,7 +17,6 @@
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.hibernate.event.service.spi.EventListenerGroup; import org.hibernate.event.service.spi.EventListenerGroup;
import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.PostCommitDeleteEventListener; import org.hibernate.event.spi.PostCommitDeleteEventListener;
import org.hibernate.event.spi.PostDeleteEvent; import org.hibernate.event.spi.PostDeleteEvent;
import org.hibernate.event.spi.PostDeleteEventListener; import org.hibernate.event.spi.PostDeleteEventListener;
@ -154,7 +153,7 @@ public void execute() throws HibernateException {
protected boolean preDelete() { protected boolean preDelete() {
boolean veto = false; boolean veto = false;
final EventListenerGroup<PreDeleteEventListener> listenerGroup = listenerGroup( EventType.PRE_DELETE ); final EventListenerGroup<PreDeleteEventListener> listenerGroup = getFastSessionServices().eventListenerGroup_PRE_DELETE;
if ( listenerGroup.isEmpty() ) { if ( listenerGroup.isEmpty() ) {
return veto; return veto;
} }
@ -166,47 +165,49 @@ protected boolean preDelete() {
} }
protected void postDelete() { protected void postDelete() {
final EventListenerGroup<PostDeleteEventListener> listenerGroup = listenerGroup( EventType.POST_DELETE ); getFastSessionServices()
if ( listenerGroup.isEmpty() ) { .eventListenerGroup_POST_DELETE
return; .fireLazyEventOnEachListener( this::newPostDeleteEvent, PostDeleteEventListener::onPostDelete );
} }
final PostDeleteEvent event = new PostDeleteEvent(
PostDeleteEvent newPostDeleteEvent() {
return new PostDeleteEvent(
getInstance(), getInstance(),
getId(), getId(),
state, state,
getPersister(), getPersister(),
eventSource() eventSource()
); );
for ( PostDeleteEventListener listener : listenerGroup.listeners() ) { }
protected void postCommitDelete(boolean success) {
final EventListenerGroup<PostDeleteEventListener> eventListeners = getFastSessionServices()
.eventListenerGroup_POST_COMMIT_DELETE;
if (success) {
eventListeners.fireLazyEventOnEachListener( this::newPostDeleteEvent, EntityDeleteAction::postCommitDeleteOnSuccess );
}
else {
eventListeners.fireLazyEventOnEachListener( this::newPostDeleteEvent, EntityDeleteAction::postCommitDeleteOnUnsuccessful );
}
}
private static void postCommitDeleteOnSuccess(PostDeleteEventListener listener, PostDeleteEvent event) {
if ( listener instanceof PostCommitDeleteEventListener ) {
listener.onPostDelete( event );
}
else {
//default to the legacy implementation that always fires the event
listener.onPostDelete( event ); listener.onPostDelete( event );
} }
} }
protected void postCommitDelete(boolean success) { private static void postCommitDeleteOnUnsuccessful(PostDeleteEventListener listener, PostDeleteEvent event) {
final EventListenerGroup<PostDeleteEventListener> listenerGroup = listenerGroup( EventType.POST_COMMIT_DELETE ); if ( listener instanceof PostCommitDeleteEventListener ) {
if ( listenerGroup.isEmpty() ) { ( (PostCommitDeleteEventListener) listener ).onPostDeleteCommitFailed( event );
return;
} }
final PostDeleteEvent event = new PostDeleteEvent( else {
getInstance(), //default to the legacy implementation that always fires the event
getId(), listener.onPostDelete( event );
state,
getPersister(),
eventSource()
);
for ( PostDeleteEventListener listener : listenerGroup.listeners() ) {
if ( PostCommitDeleteEventListener.class.isInstance( listener ) ) {
if ( success ) {
listener.onPostDelete( event );
}
else {
((PostCommitDeleteEventListener) listener).onPostDeleteCommitFailed( event );
}
}
else {
//default to the legacy implementation that always fires the event
listener.onPostDelete( event );
}
} }
} }
@ -228,7 +229,7 @@ public void doAfterTransactionCompletion(boolean success, SharedSessionContractI
@Override @Override
protected boolean hasPostCommitEventListeners() { protected boolean hasPostCommitEventListeners() {
final EventListenerGroup<PostDeleteEventListener> group = listenerGroup( EventType.POST_COMMIT_DELETE ); final EventListenerGroup<PostDeleteEventListener> group = getFastSessionServices().eventListenerGroup_POST_COMMIT_DELETE;
for ( PostDeleteEventListener listener : group.listeners() ) { for ( PostDeleteEventListener listener : group.listeners() ) {
if ( listener.requiresPostCommitHandling( getPersister() ) ) { if ( listener.requiresPostCommitHandling( getPersister() ) ) {
return true; return true;

View File

@ -121,7 +121,7 @@ public boolean needsAfterTransactionCompletion() {
@Override @Override
protected boolean hasPostCommitEventListeners() { protected boolean hasPostCommitEventListeners() {
final EventListenerGroup<PostInsertEventListener> group = listenerGroup( EventType.POST_COMMIT_INSERT ); final EventListenerGroup<PostInsertEventListener> group = getFastSessionServices().eventListenerGroup_POST_COMMIT_INSERT;
for ( PostInsertEventListener listener : group.listeners() ) { for ( PostInsertEventListener listener : group.listeners() ) {
if ( listener.requiresPostCommitHandling( getPersister() ) ) { if ( listener.requiresPostCommitHandling( getPersister() ) ) {
return true; return true;
@ -142,57 +142,42 @@ public void doAfterTransactionCompletion(boolean success, SharedSessionContractI
} }
protected void postInsert() { protected void postInsert() {
final EventSource eventSource = eventSource();
if ( isDelayed ) { if ( isDelayed ) {
eventSource.getPersistenceContextInternal().replaceDelayedEntityIdentityInsertKeys( delayedEntityKey, generatedId ); eventSource().getPersistenceContextInternal().replaceDelayedEntityIdentityInsertKeys( delayedEntityKey, generatedId );
}
final EventListenerGroup<PostInsertEventListener> listenerGroup = listenerGroup( EventType.POST_INSERT );
if ( listenerGroup.isEmpty() ) {
return;
}
final PostInsertEvent event = new PostInsertEvent(
getInstance(),
generatedId,
getState(),
getPersister(),
eventSource
);
for ( PostInsertEventListener listener : listenerGroup.listeners() ) {
listener.onPostInsert( event );
} }
getFastSessionServices()
.eventListenerGroup_POST_INSERT
.fireLazyEventOnEachListener( this::newPostInsertEvent, PostInsertEventListener::onPostInsert );
} }
protected void postCommitInsert(boolean success) { PostInsertEvent newPostInsertEvent() {
final EventListenerGroup<PostInsertEventListener> listenerGroup = listenerGroup( EventType.POST_COMMIT_INSERT ); return new PostInsertEvent(
if ( listenerGroup.isEmpty() ) {
return;
}
final PostInsertEvent event = new PostInsertEvent(
getInstance(), getInstance(),
generatedId, generatedId,
getState(), getState(),
getPersister(), getPersister(),
eventSource() eventSource()
); );
for ( PostInsertEventListener listener : listenerGroup.listeners() ) { }
if ( PostCommitInsertEventListener.class.isInstance( listener ) ) {
if ( success ) { protected void postCommitInsert(boolean success) {
listener.onPostInsert( event ); getFastSessionServices()
} .eventListenerGroup_POST_COMMIT_INSERT
else { .fireLazyEventOnEachListener( this::newPostInsertEvent, success ? PostInsertEventListener::onPostInsert : this::postCommitInsertOnFailure );
((PostCommitInsertEventListener) listener).onPostInsertCommitFailed( event ); }
}
} private void postCommitInsertOnFailure(PostInsertEventListener listener, PostInsertEvent event) {
else { if ( listener instanceof PostCommitInsertEventListener ) {
//default to the legacy implementation that always fires the event ((PostCommitInsertEventListener) listener).onPostInsertCommitFailed( event );
listener.onPostInsert( event ); }
} else {
//default to the legacy implementation that always fires the event
listener.onPostInsert( event );
} }
} }
protected boolean preInsert() { protected boolean preInsert() {
final EventListenerGroup<PreInsertEventListener> listenerGroup = listenerGroup( EventType.PRE_INSERT ); final EventListenerGroup<PreInsertEventListener> listenerGroup = getFastSessionServices().eventListenerGroup_PRE_INSERT;
if ( listenerGroup.isEmpty() ) { if ( listenerGroup.isEmpty() ) {
// NO_VETO // NO_VETO
return false; return false;

View File

@ -171,54 +171,41 @@ protected boolean cacheInsert(EntityPersister persister, Object ck) {
} }
protected void postInsert() { protected void postInsert() {
final EventListenerGroup<PostInsertEventListener> listenerGroup = listenerGroup( EventType.POST_INSERT ); getFastSessionServices()
if ( listenerGroup.isEmpty() ) { .eventListenerGroup_POST_INSERT
return; .fireLazyEventOnEachListener( this::newPostInsertEvent, PostInsertEventListener::onPostInsert );
} }
final PostInsertEvent event = new PostInsertEvent(
private PostInsertEvent newPostInsertEvent() {
return new PostInsertEvent(
getInstance(), getInstance(),
getId(), getId(),
getState(), getState(),
getPersister(), getPersister(),
eventSource() eventSource()
); );
for ( PostInsertEventListener listener : listenerGroup.listeners() ) {
listener.onPostInsert( event );
}
} }
protected void postCommitInsert(boolean success) { protected void postCommitInsert(boolean success) {
final EventListenerGroup<PostInsertEventListener> listenerGroup = listenerGroup( EventType.POST_COMMIT_INSERT ); getFastSessionServices()
if ( listenerGroup.isEmpty() ) { .eventListenerGroup_POST_COMMIT_INSERT
return; .fireLazyEventOnEachListener( this::newPostInsertEvent, success ? PostInsertEventListener::onPostInsert : this::postCommitOnFailure );
}
private void postCommitOnFailure(PostInsertEventListener listener, PostInsertEvent event) {
if ( listener instanceof PostCommitInsertEventListener ) {
((PostCommitInsertEventListener) listener).onPostInsertCommitFailed( event );
} }
final PostInsertEvent event = new PostInsertEvent( else {
getInstance(), //default to the legacy implementation that always fires the event
getId(), listener.onPostInsert( event );
getState(),
getPersister(),
eventSource()
);
for ( PostInsertEventListener listener : listenerGroup.listeners() ) {
if ( PostCommitInsertEventListener.class.isInstance( listener ) ) {
if ( success ) {
listener.onPostInsert( event );
}
else {
((PostCommitInsertEventListener) listener).onPostInsertCommitFailed( event );
}
}
else {
//default to the legacy implementation that always fires the event
listener.onPostInsert( event );
}
} }
} }
protected boolean preInsert() { protected boolean preInsert() {
boolean veto = false; boolean veto = false;
final EventListenerGroup<PreInsertEventListener> listenerGroup = listenerGroup( EventType.PRE_INSERT ); final EventListenerGroup<PreInsertEventListener> listenerGroup = getFastSessionServices().eventListenerGroup_PRE_INSERT;
if ( listenerGroup.isEmpty() ) { if ( listenerGroup.isEmpty() ) {
return veto; return veto;
} }
@ -263,13 +250,12 @@ protected boolean cacheAfterInsert(EntityDataAccess cache, Object ck) {
@Override @Override
protected boolean hasPostCommitEventListeners() { protected boolean hasPostCommitEventListeners() {
final EventListenerGroup<PostInsertEventListener> group = listenerGroup( EventType.POST_COMMIT_INSERT ); final EventListenerGroup<PostInsertEventListener> group = getFastSessionServices().eventListenerGroup_POST_COMMIT_INSERT;
for ( PostInsertEventListener listener : group.listeners() ) { for ( PostInsertEventListener listener : group.listeners() ) {
if ( listener.requiresPostCommitHandling( getPersister() ) ) { if ( listener.requiresPostCommitHandling( getPersister() ) ) {
return true; return true;
} }
} }
return false; return false;
} }

View File

@ -288,7 +288,7 @@ protected boolean cacheUpdate(EntityPersister persister, Object previousVersion,
protected boolean preUpdate() { protected boolean preUpdate() {
boolean veto = false; boolean veto = false;
final EventListenerGroup<PreUpdateEventListener> listenerGroup = listenerGroup( EventType.PRE_UPDATE ); final EventListenerGroup<PreUpdateEventListener> listenerGroup = getFastSessionServices().eventListenerGroup_PRE_UPDATE;
if ( listenerGroup.isEmpty() ) { if ( listenerGroup.isEmpty() ) {
return veto; return veto;
} }
@ -307,11 +307,13 @@ protected boolean preUpdate() {
} }
protected void postUpdate() { protected void postUpdate() {
final EventListenerGroup<PostUpdateEventListener> listenerGroup = listenerGroup( EventType.POST_UPDATE ); getFastSessionServices()
if ( listenerGroup.isEmpty() ) { .eventListenerGroup_POST_UPDATE
return; .fireLazyEventOnEachListener( this::newPostUpdateEvent, PostUpdateEventListener::onPostUpdate );
} }
final PostUpdateEvent event = new PostUpdateEvent(
private PostUpdateEvent newPostUpdateEvent() {
return new PostUpdateEvent(
getInstance(), getInstance(),
getId(), getId(),
state, state,
@ -320,44 +322,27 @@ protected void postUpdate() {
getPersister(), getPersister(),
eventSource() eventSource()
); );
for ( PostUpdateEventListener listener : listenerGroup.listeners() ) {
listener.onPostUpdate( event );
}
} }
protected void postCommitUpdate(boolean success) { protected void postCommitUpdate(boolean success) {
final EventListenerGroup<PostUpdateEventListener> listenerGroup = listenerGroup( EventType.POST_COMMIT_UPDATE ); getFastSessionServices()
if ( listenerGroup.isEmpty() ) { .eventListenerGroup_POST_COMMIT_UPDATE
return; .fireLazyEventOnEachListener( this::newPostUpdateEvent, success ? PostUpdateEventListener::onPostUpdate : this::onPostCommitFailure );
}
private void onPostCommitFailure(PostUpdateEventListener listener, PostUpdateEvent event) {
if ( listener instanceof PostCommitUpdateEventListener ) {
((PostCommitUpdateEventListener) listener).onPostUpdateCommitFailed( event );
} }
final PostUpdateEvent event = new PostUpdateEvent( else {
getInstance(), //default to the legacy implementation that always fires the event
getId(), listener.onPostUpdate( event );
state,
previousState,
dirtyFields,
getPersister(),
eventSource()
);
for ( PostUpdateEventListener listener : listenerGroup.listeners() ) {
if ( PostCommitUpdateEventListener.class.isInstance( listener ) ) {
if ( success ) {
listener.onPostUpdate( event );
}
else {
((PostCommitUpdateEventListener) listener).onPostUpdateCommitFailed( event );
}
}
else {
//default to the legacy implementation that always fires the event
listener.onPostUpdate( event );
}
} }
} }
@Override @Override
protected boolean hasPostCommitEventListeners() { protected boolean hasPostCommitEventListeners() {
final EventListenerGroup<PostUpdateEventListener> group = listenerGroup( EventType.POST_COMMIT_UPDATE ); final EventListenerGroup<PostUpdateEventListener> group = getFastSessionServices().eventListenerGroup_POST_COMMIT_UPDATE;
for ( PostUpdateEventListener listener : group.listeners() ) { for ( PostUpdateEventListener listener : group.listeners() ) {
if ( listener.requiresPostCommitHandling( getPersister() ) ) { if ( listener.requiresPostCommitHandling( getPersister() ) ) {
return true; return true;

View File

@ -28,6 +28,7 @@
import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.Status; import org.hibernate.engine.spi.Status;
import org.hibernate.event.service.spi.EventListenerGroup;
import org.hibernate.event.service.spi.EventListenerRegistry; import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.service.spi.JpaBootstrapSensitive; import org.hibernate.event.service.spi.JpaBootstrapSensitive;
import org.hibernate.event.spi.EventSource; import org.hibernate.event.spi.EventSource;
@ -205,10 +206,8 @@ private int flushEntities(final FlushEvent event, final PersistenceContext persi
LOG.trace( "Flushing entities and processing referenced collections" ); LOG.trace( "Flushing entities and processing referenced collections" );
final EventSource source = event.getSession(); final EventSource source = event.getSession();
final Iterable<FlushEntityEventListener> flushListeners = source.getFactory().getServiceRegistry() final EventListenerGroup<FlushEntityEventListener> flushListeners = source.getFactory()
.getService( EventListenerRegistry.class ) .getFastSessionServices().eventListenerGroup_FLUSH_ENTITY;
.getEventListenerGroup( EventType.FLUSH_ENTITY )
.listeners();
// Among other things, updateReachables() will recursively load all // Among other things, updateReachables() will recursively load all
// collections that are moving roles. This might cause entities to // collections that are moving roles. This might cause entities to
@ -228,9 +227,7 @@ private int flushEntities(final FlushEvent event, final PersistenceContext persi
if ( status != Status.LOADING && status != Status.GONE ) { if ( status != Status.LOADING && status != Status.GONE ) {
final FlushEntityEvent entityEvent = new FlushEntityEvent( source, me.getKey(), entry ); final FlushEntityEvent entityEvent = new FlushEntityEvent( source, me.getKey(), entry );
for ( FlushEntityEventListener listener : flushListeners ) { flushListeners.fireEventOnEachListener( entityEvent, FlushEntityEventListener::onFlushEntity );
listener.onFlushEntity( entityEvent );
}
} }
} }

View File

@ -80,7 +80,7 @@ public interface EventListenerGroup<T> extends Serializable {
* Fires an event on each registered event listener of this group. * Fires an event on each registered event listener of this group.
* *
* Implementation note (performance): * Implementation note (performance):
* the first argument is a supplier so that events can avoid allocation when no listener is registered. * the first argument is a supplier so that events can avoid being created when no listener is registered.
* the second argument is specifically designed to avoid needing a capturing lambda. * the second argument is specifically designed to avoid needing a capturing lambda.
* *
* @param eventSupplier * @param eventSupplier
@ -88,7 +88,7 @@ public interface EventListenerGroup<T> extends Serializable {
* @param <U> the kind of event * @param <U> the kind of event
*/ */
@Incubating @Incubating
<U> void fireLazyEventOnEachListener(final Supplier<U> eventSupplier, final BiConsumer<T,U> actionOnEvent); <U> void fireLazyEventOnEachListener(final Supplier<U> eventSupplier, final BiConsumer<T,U> actionOnEvent);
/** /**
* Similar as {@link #fireLazyEventOnEachListener(Supplier, BiConsumer)} except it doesn't use a {{@link Supplier}}: * Similar as {@link #fireLazyEventOnEachListener(Supplier, BiConsumer)} except it doesn't use a {{@link Supplier}}:
@ -98,9 +98,19 @@ public interface EventListenerGroup<T> extends Serializable {
* @param <U> the kind of event * @param <U> the kind of event
*/ */
@Incubating @Incubating
<U> void fireEventOnEachListener(final U event, final BiConsumer<T,U> actionOnEvent); <U> void fireEventOnEachListener(final U event, final BiConsumer<T,U> actionOnEvent);
/**
* Similar to {@link #fireEventOnEachListener(Object, BiConsumer)}, but allows passing a third parameter
* to the consumer; our code based occasionally needs a third parameter: having this additional variant
* allows using the optimal iteration more extensively and reduce allocations.
* @param event
* @param param
* @param actionOnEvent
* @param <U>
* @param <X>
*/
@Incubating @Incubating
<U,X> void fireEventOnEachListener(final U event, X param, final EventActionWithParameter<T,U,X> actionOnEvent); <U,X> void fireEventOnEachListener(final U event, X param, final EventActionWithParameter<T,U,X> actionOnEvent);
} }

View File

@ -26,14 +26,28 @@
import org.hibernate.event.spi.DirtyCheckEventListener; import org.hibernate.event.spi.DirtyCheckEventListener;
import org.hibernate.event.spi.EventType; import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.EvictEventListener; import org.hibernate.event.spi.EvictEventListener;
import org.hibernate.event.spi.FlushEntityEventListener;
import org.hibernate.event.spi.FlushEventListener; import org.hibernate.event.spi.FlushEventListener;
import org.hibernate.event.spi.InitializeCollectionEventListener; import org.hibernate.event.spi.InitializeCollectionEventListener;
import org.hibernate.event.spi.LoadEventListener; import org.hibernate.event.spi.LoadEventListener;
import org.hibernate.event.spi.LockEventListener; import org.hibernate.event.spi.LockEventListener;
import org.hibernate.event.spi.MergeEventListener; import org.hibernate.event.spi.MergeEventListener;
import org.hibernate.event.spi.PersistEventListener; import org.hibernate.event.spi.PersistEventListener;
import org.hibernate.event.spi.PostCollectionRecreateEventListener;
import org.hibernate.event.spi.PostCollectionRemoveEventListener;
import org.hibernate.event.spi.PostCollectionUpdateEventListener;
import org.hibernate.event.spi.PostDeleteEventListener;
import org.hibernate.event.spi.PostInsertEventListener;
import org.hibernate.event.spi.PostLoadEvent; import org.hibernate.event.spi.PostLoadEvent;
import org.hibernate.event.spi.PostLoadEventListener; import org.hibernate.event.spi.PostLoadEventListener;
import org.hibernate.event.spi.PostUpdateEventListener;
import org.hibernate.event.spi.PreCollectionRecreateEventListener;
import org.hibernate.event.spi.PreCollectionRemoveEventListener;
import org.hibernate.event.spi.PreCollectionUpdateEventListener;
import org.hibernate.event.spi.PreDeleteEventListener;
import org.hibernate.event.spi.PreInsertEventListener;
import org.hibernate.event.spi.PreLoadEventListener;
import org.hibernate.event.spi.PreUpdateEventListener;
import org.hibernate.event.spi.RefreshEventListener; import org.hibernate.event.spi.RefreshEventListener;
import org.hibernate.event.spi.ReplicateEventListener; import org.hibernate.event.spi.ReplicateEventListener;
import org.hibernate.event.spi.ResolveNaturalIdEventListener; import org.hibernate.event.spi.ResolveNaturalIdEventListener;
@ -89,28 +103,44 @@ public final class FastSessionServices {
*/ */
final Map<String, Object> defaultSessionProperties; final Map<String, Object> defaultSessionProperties;
// All session events need to be iterated frequently: // All session events need to be iterated frequently; CollectionAction and EventAction also need
final EventListenerGroup<AutoFlushEventListener> eventListenerGroup_AUTO_FLUSH; // most of these very frequently:
final EventListenerGroup<ClearEventListener> eventListenerGroup_CLEAR; public final EventListenerGroup<AutoFlushEventListener> eventListenerGroup_AUTO_FLUSH;
final EventListenerGroup<DeleteEventListener> eventListenerGroup_DELETE; public final EventListenerGroup<ClearEventListener> eventListenerGroup_CLEAR;
final EventListenerGroup<DirtyCheckEventListener> eventListenerGroup_DIRTY_CHECK; public final EventListenerGroup<DeleteEventListener> eventListenerGroup_DELETE;
final EventListenerGroup<EvictEventListener> eventListenerGroup_EVICT; public final EventListenerGroup<DirtyCheckEventListener> eventListenerGroup_DIRTY_CHECK;
final EventListenerGroup<FlushEventListener> eventListenerGroup_FLUSH; public final EventListenerGroup<EvictEventListener> eventListenerGroup_EVICT;
final EventListenerGroup<InitializeCollectionEventListener> eventListenerGroup_INIT_COLLECTION; public final EventListenerGroup<FlushEntityEventListener> eventListenerGroup_FLUSH_ENTITY;
final EventListenerGroup<LoadEventListener> eventListenerGroup_LOAD; public final EventListenerGroup<FlushEventListener> eventListenerGroup_FLUSH;
final EventListenerGroup<LockEventListener> eventListenerGroup_LOCK; public final EventListenerGroup<InitializeCollectionEventListener> eventListenerGroup_INIT_COLLECTION;
final EventListenerGroup<MergeEventListener> eventListenerGroup_MERGE; public final EventListenerGroup<LoadEventListener> eventListenerGroup_LOAD;
final EventListenerGroup<PersistEventListener> eventListenerGroup_PERSIST; public final EventListenerGroup<LockEventListener> eventListenerGroup_LOCK;
final EventListenerGroup<PersistEventListener> eventListenerGroup_PERSIST_ONFLUSH; public final EventListenerGroup<MergeEventListener> eventListenerGroup_MERGE;
final EventListenerGroup<RefreshEventListener> eventListenerGroup_REFRESH; public final EventListenerGroup<PersistEventListener> eventListenerGroup_PERSIST;
final EventListenerGroup<ReplicateEventListener> eventListenerGroup_REPLICATE; public final EventListenerGroup<PersistEventListener> eventListenerGroup_PERSIST_ONFLUSH;
final EventListenerGroup<ResolveNaturalIdEventListener> eventListenerGroup_RESOLVE_NATURAL_ID; public final EventListenerGroup<PostCollectionRecreateEventListener> eventListenerGroup_POST_COLLECTION_RECREATE;
final EventListenerGroup<SaveOrUpdateEventListener> eventListenerGroup_SAVE; public final EventListenerGroup<PostCollectionRemoveEventListener> eventListenerGroup_POST_COLLECTION_REMOVE;
final EventListenerGroup<SaveOrUpdateEventListener> eventListenerGroup_SAVE_UPDATE; public final EventListenerGroup<PostCollectionUpdateEventListener> eventListenerGroup_POST_COLLECTION_UPDATE;
final EventListenerGroup<SaveOrUpdateEventListener> eventListenerGroup_UPDATE; public final EventListenerGroup<PostDeleteEventListener> eventListenerGroup_POST_COMMIT_DELETE;
public final EventListenerGroup<PostDeleteEventListener> eventListenerGroup_POST_DELETE;
//Frequently used by 2LC initialization: public final EventListenerGroup<PostInsertEventListener> eventListenerGroup_POST_COMMIT_INSERT;
final EventListenerGroup<PostLoadEventListener> eventListenerGroup_POST_LOAD; public final EventListenerGroup<PostInsertEventListener> eventListenerGroup_POST_INSERT;
public final EventListenerGroup<PostLoadEventListener> eventListenerGroup_POST_LOAD; //Frequently used by 2LC initialization:
public final EventListenerGroup<PostUpdateEventListener> eventListenerGroup_POST_COMMIT_UPDATE;
public final EventListenerGroup<PostUpdateEventListener> eventListenerGroup_POST_UPDATE;
public final EventListenerGroup<PreCollectionRecreateEventListener> eventListenerGroup_PRE_COLLECTION_RECREATE;
public final EventListenerGroup<PreCollectionRemoveEventListener> eventListenerGroup_PRE_COLLECTION_REMOVE;
public final EventListenerGroup<PreCollectionUpdateEventListener> eventListenerGroup_PRE_COLLECTION_UPDATE;
public final EventListenerGroup<PreDeleteEventListener> eventListenerGroup_PRE_DELETE;
public final EventListenerGroup<PreInsertEventListener> eventListenerGroup_PRE_INSERT;
public final EventListenerGroup<PreLoadEventListener> eventListenerGroup_PRE_LOAD;
public final EventListenerGroup<PreUpdateEventListener> eventListenerGroup_PRE_UPDATE;
public final EventListenerGroup<RefreshEventListener> eventListenerGroup_REFRESH;
public final EventListenerGroup<ReplicateEventListener> eventListenerGroup_REPLICATE;
public final EventListenerGroup<ResolveNaturalIdEventListener> eventListenerGroup_RESOLVE_NATURAL_ID;
public final EventListenerGroup<SaveOrUpdateEventListener> eventListenerGroup_SAVE;
public final EventListenerGroup<SaveOrUpdateEventListener> eventListenerGroup_SAVE_UPDATE;
public final EventListenerGroup<SaveOrUpdateEventListener> eventListenerGroup_UPDATE;
//Intentionally Package private: //Intentionally Package private:
final boolean disallowOutOfTransactionUpdateOperations; final boolean disallowOutOfTransactionUpdateOperations;
@ -148,19 +178,36 @@ public final class FastSessionServices {
this.eventListenerGroup_DIRTY_CHECK = listeners( eventListenerRegistry, EventType.DIRTY_CHECK ); this.eventListenerGroup_DIRTY_CHECK = listeners( eventListenerRegistry, EventType.DIRTY_CHECK );
this.eventListenerGroup_EVICT = listeners( eventListenerRegistry, EventType.EVICT ); this.eventListenerGroup_EVICT = listeners( eventListenerRegistry, EventType.EVICT );
this.eventListenerGroup_FLUSH = listeners( eventListenerRegistry, EventType.FLUSH ); this.eventListenerGroup_FLUSH = listeners( eventListenerRegistry, EventType.FLUSH );
this.eventListenerGroup_FLUSH_ENTITY = listeners( eventListenerRegistry, EventType.FLUSH_ENTITY );
this.eventListenerGroup_INIT_COLLECTION = listeners( eventListenerRegistry, EventType.INIT_COLLECTION ); this.eventListenerGroup_INIT_COLLECTION = listeners( eventListenerRegistry, EventType.INIT_COLLECTION );
this.eventListenerGroup_LOAD = listeners( eventListenerRegistry, EventType.LOAD ); this.eventListenerGroup_LOAD = listeners( eventListenerRegistry, EventType.LOAD );
this.eventListenerGroup_LOCK = listeners( eventListenerRegistry, EventType.LOCK ); this.eventListenerGroup_LOCK = listeners( eventListenerRegistry, EventType.LOCK );
this.eventListenerGroup_MERGE = listeners( eventListenerRegistry, EventType.MERGE ); this.eventListenerGroup_MERGE = listeners( eventListenerRegistry, EventType.MERGE );
this.eventListenerGroup_PERSIST = listeners( eventListenerRegistry, EventType.PERSIST ); this.eventListenerGroup_PERSIST = listeners( eventListenerRegistry, EventType.PERSIST );
this.eventListenerGroup_PERSIST_ONFLUSH = listeners( eventListenerRegistry, EventType.PERSIST_ONFLUSH ); this.eventListenerGroup_PERSIST_ONFLUSH = listeners( eventListenerRegistry, EventType.PERSIST_ONFLUSH );
this.eventListenerGroup_POST_COLLECTION_RECREATE = listeners( eventListenerRegistry, EventType.POST_COLLECTION_RECREATE );
this.eventListenerGroup_POST_COLLECTION_REMOVE = listeners( eventListenerRegistry, EventType.POST_COLLECTION_REMOVE );
this.eventListenerGroup_POST_COLLECTION_UPDATE = listeners( eventListenerRegistry, EventType.POST_COLLECTION_UPDATE );
this.eventListenerGroup_POST_COMMIT_DELETE = listeners( eventListenerRegistry, EventType.POST_COMMIT_DELETE );
this.eventListenerGroup_POST_COMMIT_INSERT = listeners( eventListenerRegistry, EventType.POST_COMMIT_INSERT );
this.eventListenerGroup_POST_COMMIT_UPDATE = listeners( eventListenerRegistry, EventType.POST_COMMIT_UPDATE );
this.eventListenerGroup_POST_DELETE = listeners( eventListenerRegistry, EventType.POST_DELETE );
this.eventListenerGroup_POST_INSERT = listeners( eventListenerRegistry, EventType.POST_INSERT );
this.eventListenerGroup_POST_LOAD = listeners( eventListenerRegistry, EventType.POST_LOAD );
this.eventListenerGroup_POST_UPDATE = listeners( eventListenerRegistry, EventType.POST_UPDATE );
this.eventListenerGroup_PRE_COLLECTION_RECREATE = listeners( eventListenerRegistry, EventType.PRE_COLLECTION_RECREATE );
this.eventListenerGroup_PRE_COLLECTION_REMOVE = listeners( eventListenerRegistry, EventType.PRE_COLLECTION_REMOVE );
this.eventListenerGroup_PRE_COLLECTION_UPDATE = listeners( eventListenerRegistry, EventType.PRE_COLLECTION_UPDATE );
this.eventListenerGroup_PRE_DELETE = listeners( eventListenerRegistry, EventType.PRE_DELETE );
this.eventListenerGroup_PRE_INSERT = listeners( eventListenerRegistry, EventType.PRE_INSERT );
this.eventListenerGroup_PRE_LOAD = listeners( eventListenerRegistry, EventType.PRE_LOAD );
this.eventListenerGroup_PRE_UPDATE = listeners( eventListenerRegistry, EventType.PRE_UPDATE );
this.eventListenerGroup_REFRESH = listeners( eventListenerRegistry, EventType.REFRESH ); this.eventListenerGroup_REFRESH = listeners( eventListenerRegistry, EventType.REFRESH );
this.eventListenerGroup_REPLICATE = listeners( eventListenerRegistry, EventType.REPLICATE ); this.eventListenerGroup_REPLICATE = listeners( eventListenerRegistry, EventType.REPLICATE );
this.eventListenerGroup_RESOLVE_NATURAL_ID = listeners( eventListenerRegistry, EventType.RESOLVE_NATURAL_ID ); this.eventListenerGroup_RESOLVE_NATURAL_ID = listeners( eventListenerRegistry, EventType.RESOLVE_NATURAL_ID );
this.eventListenerGroup_SAVE = listeners( eventListenerRegistry, EventType.SAVE ); this.eventListenerGroup_SAVE = listeners( eventListenerRegistry, EventType.SAVE );
this.eventListenerGroup_SAVE_UPDATE = listeners( eventListenerRegistry, EventType.SAVE_UPDATE ); this.eventListenerGroup_SAVE_UPDATE = listeners( eventListenerRegistry, EventType.SAVE_UPDATE );
this.eventListenerGroup_UPDATE = listeners( eventListenerRegistry, EventType.UPDATE ); this.eventListenerGroup_UPDATE = listeners( eventListenerRegistry, EventType.UPDATE );
this.eventListenerGroup_POST_LOAD = listeners( eventListenerRegistry, EventType.POST_LOAD );
//Other highly useful constants: //Other highly useful constants:
this.dialect = jdbcServices.getJdbcEnvironment().getDialect(); this.dialect = jdbcServices.getJdbcEnvironment().getDialect();
@ -186,6 +233,7 @@ public final class FastSessionServices {
this.defaultSessionEventListeners = sessionFactoryOptions.getBaselineSessionEventsListenerBuilder(); this.defaultSessionEventListeners = sessionFactoryOptions.getBaselineSessionEventsListenerBuilder();
this.defaultLockOptions = initializeDefaultLockOptions( defaultSessionProperties ); this.defaultLockOptions = initializeDefaultLockOptions( defaultSessionProperties );
this.initialSessionFlushMode = initializeDefaultFlushMode( defaultSessionProperties ); this.initialSessionFlushMode = initializeDefaultFlushMode( defaultSessionProperties );
} }
private static FlushMode initializeDefaultFlushMode(Map<String, Object> defaultSessionProperties) { private static FlushMode initializeDefaultFlushMode(Map<String, Object> defaultSessionProperties) {

View File

@ -1191,9 +1191,8 @@ private void initializeEntitiesAndCollections(
if ( hydratedObjectsSize != 0 ) { if ( hydratedObjectsSize != 0 ) {
final Iterable<PreLoadEventListener> listeners = session final Iterable<PreLoadEventListener> listeners = session
.getFactory() .getFactory()
.getServiceRegistry() .getFastSessionServices()
.getService( EventListenerRegistry.class ) .eventListenerGroup_PRE_LOAD
.getEventListenerGroup( EventType.PRE_LOAD )
.listeners(); .listeners();
for ( Object hydratedObject : hydratedObjects ) { for ( Object hydratedObject : hydratedObjects ) {

View File

@ -239,9 +239,8 @@ private void performTwoPhaseLoad(
final SharedSessionContractImplementor session = context.getSession(); final SharedSessionContractImplementor session = context.getSession();
final Iterable<PreLoadEventListener> listeners = session final Iterable<PreLoadEventListener> listeners = session
.getFactory() .getFactory()
.getServiceRegistry() .getFastSessionServices()
.getService( EventListenerRegistry.class ) .eventListenerGroup_PRE_LOAD
.getEventListenerGroup( EventType.PRE_LOAD )
.listeners(); .listeners();
for ( HydratedEntityRegistration registration : hydratedEntityRegistrations ) { for ( HydratedEntityRegistration registration : hydratedEntityRegistrations ) {