HHH-11264 - Unify native and JPA implementations of Hibernate event listeners

This commit is contained in:
Andrea Boriero 2018-03-03 16:58:55 +00:00 committed by Steve Ebersole
parent 8f889e95d7
commit 55e73c7202
56 changed files with 414 additions and 1003 deletions

View File

@ -173,14 +173,6 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont
return this;
}
// @Override
// public MetadataBuilder applyReflectionManager(ReflectionManager reflectionManager) {
// bootstrapContext.
// this.options.reflectionManager = reflectionManager;
// this.options.reflectionManager.injectClassLoaderDelegate( this.options.getHcannClassLoaderDelegate() );
// return this;
// }
@Override
public MetadataBuilder applySharedCacheMode(SharedCacheMode sharedCacheMode) {
this.options.sharedCacheMode = sharedCacheMode;

View File

@ -471,7 +471,7 @@ public class CascadingActions {
*
* @return The children iterator.
*/
private static Iterator getAllElementsIterator(
public static Iterator getAllElementsIterator(
EventSource session,
CollectionType collectionType,
Object collection) {

View File

@ -7,6 +7,7 @@
package org.hibernate.event.internal;
import java.io.Serializable;
import java.util.IdentityHashMap;
import java.util.Map;
import org.hibernate.HibernateException;
@ -28,6 +29,7 @@ import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.Status;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.service.spi.JpaBootstrapSensitive;
import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.FlushEntityEvent;
@ -46,10 +48,17 @@ import org.jboss.logging.Logger;
*
* @author Steve Ebersole
*/
public abstract class AbstractFlushingEventListener implements Serializable {
public abstract class AbstractFlushingEventListener implements JpaBootstrapSensitive, Serializable {
private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class, AbstractFlushingEventListener.class.getName() );
private boolean jpaBootstrap;
@Override
public void wasJpaBootstrap(boolean wasJpaBootstrap) {
this.jpaBootstrap = wasJpaBootstrap;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Pre-flushing section
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -155,12 +164,22 @@ public abstract class AbstractFlushingEventListener implements Serializable {
}
protected Object getAnything() {
if ( jpaBootstrap ) {
return new IdentityHashMap( 10 );
}
else {
return null;
}
}
protected CascadingAction getCascadingAction() {
if ( jpaBootstrap ) {
return CascadingActions.PERSIST_ON_FLUSH;
}
else {
return CascadingActions.SAVE_UPDATE;
}
}
/**
* Initialize the flags of the CollectionEntry, including the

View File

@ -32,6 +32,8 @@ import org.hibernate.id.IdentifierGenerationException;
import org.hibernate.id.IdentifierGeneratorHelper;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.jpa.event.spi.CallbackRegistry;
import org.hibernate.jpa.event.spi.CallbackRegistryConsumer;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.type.Type;
@ -45,13 +47,21 @@ import static org.hibernate.FlushMode.MANUAL;
*
* @author Steve Ebersole.
*/
public abstract class AbstractSaveEventListener extends AbstractReassociateEventListener {
public abstract class AbstractSaveEventListener
extends AbstractReassociateEventListener
implements CallbackRegistryConsumer {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( AbstractSaveEventListener.class );
public static enum EntityState {
public enum EntityState {
PERSISTENT, TRANSIENT, DETACHED, DELETED
}
private CallbackRegistry callbackRegistry;
public void injectCallbackRegistry(CallbackRegistry callbackRegistry) {
this.callbackRegistry = callbackRegistry;
}
/**
* Prepares the save call using the given requested id.
*
@ -69,6 +79,8 @@ public abstract class AbstractSaveEventListener extends AbstractReassociateEvent
String entityName,
Object anything,
EventSource source) {
callbackRegistry.preCreate( entity );
return performSave(
entity,
requestedId,
@ -101,6 +113,8 @@ public abstract class AbstractSaveEventListener extends AbstractReassociateEvent
Object anything,
EventSource source,
boolean requiresImmediateIdAccess) {
callbackRegistry.preCreate( entity );
if ( entity instanceof SelfDirtinessTracker ) {
( (SelfDirtinessTracker) entity ).$$_hibernate_clearDirtyAttributes();
}

View File

@ -25,12 +25,15 @@ import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.Status;
import org.hibernate.event.service.spi.JpaBootstrapSensitive;
import org.hibernate.event.spi.DeleteEvent;
import org.hibernate.event.spi.DeleteEventListener;
import org.hibernate.event.spi.EventSource;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.collections.IdentitySet;
import org.hibernate.jpa.event.spi.CallbackRegistry;
import org.hibernate.jpa.event.spi.CallbackRegistryConsumer;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.type.Type;
@ -42,9 +45,22 @@ import org.hibernate.type.TypeHelper;
*
* @author Steve Ebersole
*/
public class DefaultDeleteEventListener implements DeleteEventListener {
public class DefaultDeleteEventListener implements DeleteEventListener, CallbackRegistryConsumer, JpaBootstrapSensitive {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( DefaultDeleteEventListener.class );
private CallbackRegistry callbackRegistry;
private boolean jpaBootstrap;
@Override
public void injectCallbackRegistry(CallbackRegistry callbackRegistry) {
this.callbackRegistry = callbackRegistry;
}
@Override
public void wasJpaBootstrap(boolean wasJpaBootstrap) {
this.jpaBootstrap = wasJpaBootstrap;
}
/**
* Handle the given delete event.
*
@ -163,10 +179,22 @@ public class DefaultDeleteEventListener implements DeleteEventListener {
* @param event The event.
*/
protected void performDetachedEntityDeletionCheck(DeleteEvent event) {
if ( jpaBootstrap ) {
disallowDeletionOfDetached( event );
}
// ok in normal Hibernate usage to delete a detached entity; JPA however
// forbids it, thus this is a hook for HEM to affect this behavior
}
private void disallowDeletionOfDetached(DeleteEvent event) {
EventSource source = event.getSession();
String entityName = event.getEntityName();
EntityPersister persister = source.getEntityPersister( entityName, event.getObject() );
Serializable id = persister.getIdentifier( event.getObject(), source );
entityName = entityName == null ? source.guessEntityName( event.getObject() ) : entityName;
throw new IllegalArgumentException("Removing a detached instance "+ entityName + "#" + id);
}
/**
* We encountered a delete request on a transient instance.
* <p/>
@ -310,6 +338,8 @@ public class DefaultDeleteEventListener implements DeleteEventListener {
}
protected boolean invokeDeleteLifecycle(EventSource session, Object entity, EntityPersister persister) {
callbackRegistry.preRemove( entity );
if ( persister.implementsLifecycle() ) {
LOG.debug( "Calling onDelete()" );
if ( ( (Lifecycle) entity ).onDelete( session ) ) {

View File

@ -12,10 +12,11 @@ import java.util.Arrays;
import org.hibernate.AssertionFailure;
import org.hibernate.CustomEntityDirtinessStrategy;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.StaleObjectStateException;
import org.hibernate.action.internal.DelayedPostInsertIdentifier;
import org.hibernate.action.internal.EntityUpdateAction;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
import org.hibernate.engine.internal.Nullability;
import org.hibernate.engine.internal.Versioning;
import org.hibernate.engine.spi.EntityEntry;
@ -29,6 +30,9 @@ import org.hibernate.event.spi.FlushEntityEventListener;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.jpa.event.spi.CallbackRegistry;
import org.hibernate.jpa.event.spi.CallbackRegistryConsumer;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.type.Type;
@ -38,9 +42,16 @@ import org.hibernate.type.Type;
*
* @author Gavin King
*/
public class DefaultFlushEntityEventListener implements FlushEntityEventListener {
public class DefaultFlushEntityEventListener implements FlushEntityEventListener, CallbackRegistryConsumer {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( DefaultFlushEntityEventListener.class );
private CallbackRegistry callbackRegistry;
@Override
public void injectCallbackRegistry(CallbackRegistry callbackRegistry) {
this.callbackRegistry = callbackRegistry;
}
/**
* make sure user didn't mangle the id
*/
@ -341,7 +352,14 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
EntityEntry entry,
final Object[] values,
EntityPersister persister) {
return session.getInterceptor().onFlushDirty(
boolean isDirty = false;
if ( entry.getStatus() != Status.DELETED ) {
if ( callbackRegistry.preUpdate( entity ) ) {
isDirty = copyState( entity, persister.getPropertyTypes(), values, session.getFactory() );
}
}
final boolean answerFromInterceptor = session.getInterceptor().onFlushDirty(
entity,
entry.getId(),
values,
@ -349,6 +367,25 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
persister.getPropertyNames(),
persister.getPropertyTypes()
);
return answerFromInterceptor || isDirty;
}
private boolean copyState(Object entity, Type[] types, Object[] state, SessionFactory sf) {
// copy the entity state into the state array and return true if the state has changed
ClassMetadata metadata = sf.getClassMetadata( entity.getClass() );
Object[] newState = metadata.getPropertyValues( entity );
int size = newState.length;
boolean isDirty = false;
for ( int index = 0; index < size; index++ ) {
if ( ( state[index] == LazyPropertyInitializer.UNFETCHED_PROPERTY &&
newState[index] != LazyPropertyInitializer.UNFETCHED_PROPERTY ) ||
( state[index] != newState[index] && !types[index].isEqual( state[index], newState[index] ) ) ) {
isDirty = true;
state[index] = newState[index];
}
}
return isDirty;
}
/**
@ -499,7 +536,7 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
else {
// see if the custom dirtiness strategy can tell us...
class DirtyCheckContextImpl implements CustomEntityDirtinessStrategy.DirtyCheckContext {
int[] found;
private int[] found;
@Override
public void doDirtyChecking(CustomEntityDirtinessStrategy.AttributeChecker attributeChecker) {
@ -513,7 +550,7 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
session.getFactory().getCustomEntityDirtinessStrategy().findDirty(
entity,
persister,
(Session) session,
session,
context
);
dirtyProperties = context.found;

View File

@ -6,6 +6,7 @@
*/
package org.hibernate.event.internal;
import java.io.Serializable;
import java.util.IdentityHashMap;
import java.util.Map;
@ -23,6 +24,8 @@ import org.hibernate.event.spi.PersistEventListener;
import org.hibernate.id.ForeignGenerator;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.jpa.event.spi.CallbackRegistry;
import org.hibernate.jpa.event.spi.CallbackRegistryConsumer;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.proxy.HibernateProxy;
@ -34,7 +37,9 @@ import org.hibernate.proxy.LazyInitializer;
*
* @author Gavin King
*/
public class DefaultPersistEventListener extends AbstractSaveEventListener implements PersistEventListener {
public class DefaultPersistEventListener
extends AbstractSaveEventListener
implements PersistEventListener, CallbackRegistryConsumer {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( DefaultPersistEventListener.class );
@Override
@ -52,7 +57,6 @@ public class DefaultPersistEventListener extends AbstractSaveEventListener imple
*
* @param event The create event to be handled.
*
* @throws HibernateException
*/
public void onPersist(PersistEvent event) throws HibernateException {
onPersist( event, new IdentityHashMap( 10 ) );
@ -63,7 +67,6 @@ public class DefaultPersistEventListener extends AbstractSaveEventListener imple
*
* @param event The create event to be handled.
*
* @throws HibernateException
*/
public void onPersist(PersistEvent event, Map createCache) throws HibernateException {
final SessionImplementor source = event.getSession();

View File

@ -14,6 +14,8 @@ import org.hibernate.classic.Lifecycle;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.event.spi.PostLoadEvent;
import org.hibernate.event.spi.PostLoadEventListener;
import org.hibernate.jpa.event.spi.CallbackRegistry;
import org.hibernate.jpa.event.spi.CallbackRegistryConsumer;
import org.hibernate.persister.entity.EntityPersister;
/**
@ -25,10 +27,20 @@ import org.hibernate.persister.entity.EntityPersister;
* @author Gavin King
* @author Steve Ebersole
*/
public class DefaultPostLoadEventListener implements PostLoadEventListener {
public class DefaultPostLoadEventListener implements PostLoadEventListener, CallbackRegistryConsumer {
private CallbackRegistry callbackRegistry;
@Override
public void injectCallbackRegistry(CallbackRegistry callbackRegistry) {
this.callbackRegistry = callbackRegistry;
}
@Override
public void onPostLoad(PostLoadEvent event) {
final Object entity = event.getEntity();
callbackRegistry.postLoad( entity );
final EntityEntry entry = event.getSession().getPersistenceContext().getEntry( entity );
if ( entry == null ) {
throw new AssertionFailure( "possible non-threadsafe access to the session" );

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.event.internal.core;
package org.hibernate.event.internal;
import org.hibernate.event.spi.PostDeleteEvent;
import org.hibernate.event.spi.PostDeleteEventListener;
@ -14,23 +14,18 @@ import org.hibernate.jpa.event.spi.CallbackType;
import org.hibernate.persister.entity.EntityPersister;
/**
* The standard PostDeleteEventListener implementation
*
* @author <a href="mailto:kabir.khan@jboss.org">Kabir Khan</a>
* @author Steve Ebersole
*/
public class JpaPostDeleteEventListener implements PostDeleteEventListener, CallbackRegistryConsumer {
public class PostDeleteEventListenerStandardImpl implements PostDeleteEventListener, CallbackRegistryConsumer {
private CallbackRegistry callbackRegistry;
public void injectCallbackRegistry(CallbackRegistry callbackRegistry) {
this.callbackRegistry = callbackRegistry;
}
public JpaPostDeleteEventListener() {
super();
}
public JpaPostDeleteEventListener(CallbackRegistry callbackRegistry) {
this.callbackRegistry = callbackRegistry;
}
public void onPostDelete(PostDeleteEvent event) {
Object entity = event.getEntity();
callbackRegistry.postRemove( entity );

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.event.internal.core;
package org.hibernate.event.internal;
import org.hibernate.event.spi.PostInsertEvent;
import org.hibernate.event.spi.PostInsertEventListener;
@ -17,7 +17,7 @@ import org.hibernate.persister.entity.EntityPersister;
* @author <a href="mailto:kabir.khan@jboss.org">Kabir Khan</a>
* @author Steve Ebersole
*/
public class JpaPostInsertEventListener implements PostInsertEventListener, CallbackRegistryConsumer {
public class PostInsertEventListenerStandardImpl implements PostInsertEventListener, CallbackRegistryConsumer {
private CallbackRegistry callbackRegistry;
@Override
@ -25,14 +25,6 @@ public class JpaPostInsertEventListener implements PostInsertEventListener, Call
this.callbackRegistry = callbackRegistry;
}
public JpaPostInsertEventListener() {
super();
}
public JpaPostInsertEventListener(CallbackRegistry callbackRegistry) {
this.callbackRegistry = callbackRegistry;
}
@Override
public void onPostInsert(PostInsertEvent event) {
Object entity = event.getEntity();

View File

@ -0,0 +1,49 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.event.internal;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.Status;
import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.PostUpdateEvent;
import org.hibernate.event.spi.PostUpdateEventListener;
import org.hibernate.jpa.event.spi.CallbackRegistry;
import org.hibernate.jpa.event.spi.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.CallbackType;
import org.hibernate.persister.entity.EntityPersister;
/**
* @author Steve Ebersole
*/
public class PostUpdateEventListenerStandardImpl implements PostUpdateEventListener, CallbackRegistryConsumer {
private CallbackRegistry callbackRegistry;
@Override
public void injectCallbackRegistry(CallbackRegistry callbackRegistry) {
this.callbackRegistry = callbackRegistry;
}
@Override
public void onPostUpdate(PostUpdateEvent event) {
Object entity = event.getEntity();
EventSource eventSource = event.getSession();
handlePostUpdate(entity, eventSource);
}
private void handlePostUpdate(Object entity, EventSource source) {
EntityEntry entry = source.getPersistenceContext().getEntry( entity );
// mimic the preUpdate filter
if ( Status.DELETED != entry.getStatus()) {
callbackRegistry.postUpdate(entity);
}
}
@Override
public boolean requiresPostCommitHanding(EntityPersister persister) {
return callbackRegistry.hasRegisteredCallbacks( persister.getMappedClass(), CallbackType.POST_UPDATE );
}
}

View File

@ -16,19 +16,24 @@ import java.util.Set;
import org.hibernate.event.service.spi.DuplicationStrategy;
import org.hibernate.event.service.spi.EventListenerGroup;
import org.hibernate.event.service.spi.EventListenerRegistrationException;
import org.hibernate.event.service.spi.JpaBootstrapSensitive;
import org.hibernate.event.spi.EventType;
import org.hibernate.jpa.event.spi.CallbackRegistryConsumer;
/**
* @author Steve Ebersole
*/
public class EventListenerGroupImpl<T> implements EventListenerGroup<T> {
class EventListenerGroupImpl<T> implements EventListenerGroup<T> {
private EventType<T> eventType;
private final EventListenerRegistryImpl listenerRegistry;
private final Set<DuplicationStrategy> duplicationStrategies = new LinkedHashSet<DuplicationStrategy>();
private final Set<DuplicationStrategy> duplicationStrategies = new LinkedHashSet<>();
private List<T> listeners;
public EventListenerGroupImpl(EventType<T> eventType) {
public EventListenerGroupImpl(EventType<T> eventType, EventListenerRegistryImpl listenerRegistry) {
this.eventType = eventType;
this.listenerRegistry = listenerRegistry;
duplicationStrategies.add(
// At minimum make sure we do not register the same exact listener class multiple times.
new DuplicationStrategy() {
@ -76,11 +81,12 @@ public class EventListenerGroupImpl<T> implements EventListenerGroup<T> {
}
public Iterable<T> listeners() {
return listeners == null ? Collections.<T>emptyList() : listeners;
return listeners == null ? Collections.emptyList() : listeners;
}
@Override
public void appendListeners(T... listeners) {
@SafeVarargs
public final void appendListeners(T... listeners) {
for ( T listener : listeners ) {
appendListener( listener );
}
@ -94,7 +100,8 @@ public class EventListenerGroupImpl<T> implements EventListenerGroup<T> {
}
@Override
public void prependListeners(T... listeners) {
@SafeVarargs
public final void prependListeners(T... listeners) {
for ( T listener : listeners ) {
prependListener( listener );
}
@ -109,7 +116,7 @@ public class EventListenerGroupImpl<T> implements EventListenerGroup<T> {
private boolean listenerShouldGetAdded(T listener) {
if ( listeners == null ) {
listeners = new ArrayList<T>();
listeners = new ArrayList<>();
return true;
// no need to do de-dup checks
}
@ -143,9 +150,22 @@ public class EventListenerGroupImpl<T> implements EventListenerGroup<T> {
private void internalPrepend(T listener) {
checkAgainstBaseInterface( listener );
performInjections( listener );
listeners.add( 0, listener );
}
private void performInjections(T listener) {
if ( CallbackRegistryConsumer.class.isInstance( listener ) ) {
( (CallbackRegistryConsumer) listener ).injectCallbackRegistry( listenerRegistry.getCallbackRegistry() );
}
if ( JpaBootstrapSensitive.class.isInstance( listener ) ) {
( (JpaBootstrapSensitive) listener ).wasJpaBootstrap(
listenerRegistry.getSessionFactory().getSessionFactoryOptions().isJpaBootstrap()
);
}
}
private void checkAgainstBaseInterface(T listener) {
if ( !eventType.baseListenerInterface().isInstance( listener ) ) {
throw new EventListenerRegistrationException(
@ -156,6 +176,7 @@ public class EventListenerGroupImpl<T> implements EventListenerGroup<T> {
private void internalAppend(T listener) {
checkAgainstBaseInterface( listener );
performInjections( listener );
listeners.add( listener );
}
}

View File

@ -11,6 +11,9 @@ import java.util.HashMap;
import java.util.Map;
import org.hibernate.HibernateException;
import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.event.internal.DefaultAutoFlushEventListener;
import org.hibernate.event.internal.DefaultDeleteEventListener;
import org.hibernate.event.internal.DefaultDirtyCheckEventListener;
@ -31,10 +34,19 @@ import org.hibernate.event.internal.DefaultResolveNaturalIdEventListener;
import org.hibernate.event.internal.DefaultSaveEventListener;
import org.hibernate.event.internal.DefaultSaveOrUpdateEventListener;
import org.hibernate.event.internal.DefaultUpdateEventListener;
import org.hibernate.event.internal.PostDeleteEventListenerStandardImpl;
import org.hibernate.event.internal.PostInsertEventListenerStandardImpl;
import org.hibernate.event.internal.PostUpdateEventListenerStandardImpl;
import org.hibernate.event.service.spi.DuplicationStrategy;
import org.hibernate.event.service.spi.EventListenerRegistrationException;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventType;
import org.hibernate.jpa.event.internal.CallbackBuilderLegacyImpl;
import org.hibernate.jpa.event.internal.CallbackRegistryImpl;
import org.hibernate.jpa.event.spi.CallbackBuilder;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.service.spi.Stoppable;
import static org.hibernate.event.spi.EventType.AUTO_FLUSH;
import static org.hibernate.event.spi.EventType.CLEAR;
@ -76,10 +88,44 @@ import static org.hibernate.event.spi.EventType.UPDATE;
/**
* @author Steve Ebersole
*/
public class EventListenerRegistryImpl implements EventListenerRegistry {
private Map<Class,Object> listenerClassToInstanceMap = new HashMap<Class, Object>();
public class EventListenerRegistryImpl implements EventListenerRegistry, Stoppable {
private Map<Class,Object> listenerClassToInstanceMap = new HashMap<>();
private EventListenerGroupImpl[] registeredEventListeners = prepareListenerAssociation();
private final SessionFactoryImplementor sessionFactory;
private CallbackBuilder callbackBuilder;
private CallbackRegistryImpl callbackRegistry;
private EventListenerGroupImpl[] registeredEventListeners;
EventListenerRegistryImpl(BootstrapContext bootstrapContext, SessionFactoryImplementor sessionFactory) {
this.sessionFactory = sessionFactory;
this.callbackRegistry = new CallbackRegistryImpl();
this.callbackBuilder = new CallbackBuilderLegacyImpl(
bootstrapContext.getServiceRegistry().getService( ManagedBeanRegistry.class ),
bootstrapContext.getReflectionManager()
);
this.registeredEventListeners = buildListenerGroups( bootstrapContext );
}
SessionFactoryImplementor getSessionFactory() {
return sessionFactory;
}
CallbackRegistryImpl getCallbackRegistry() {
return callbackRegistry;
}
@Override
public void prepare(MetadataImplementor metadata) {
for ( PersistentClass persistentClass : metadata.getEntityBindings() ) {
if ( persistentClass.getClassName() == null ) {
// we can have non java class persisted by hibernate
continue;
}
callbackBuilder.buildCallbacksForEntity( persistentClass.getClassName(), callbackRegistry );
}
}
@SuppressWarnings({ "unchecked" })
public <T> EventListenerGroupImpl<T> getEventListenerGroup(EventType<T> eventType) {
@ -100,7 +146,8 @@ public class EventListenerRegistryImpl implements EventListenerRegistry {
}
@Override
public <T> void setListeners(EventType<T> type, Class<? extends T>... listenerClasses) {
@SafeVarargs
public final <T> void setListeners(EventType<T> type, Class<? extends T>... listenerClasses) {
setListeners( type, resolveListenerInstances( type, listenerClasses ) );
}
@ -136,37 +183,42 @@ public class EventListenerRegistryImpl implements EventListenerRegistry {
}
@Override
public <T> void setListeners(EventType<T> type, T... listeners) {
@SafeVarargs
public final <T> void setListeners(EventType<T> type, T... listeners) {
EventListenerGroupImpl<T> registeredListeners = getEventListenerGroup( type );
registeredListeners.clear();
if ( listeners != null ) {
for ( int i = 0, max = listeners.length; i < max; i++ ) {
registeredListeners.appendListener( listeners[i] );
for ( T listener : listeners ) {
registeredListeners.appendListener( listener );
}
}
}
@Override
public <T> void appendListeners(EventType<T> type, Class<? extends T>... listenerClasses) {
@SafeVarargs
public final <T> void appendListeners(EventType<T> type, Class<? extends T>... listenerClasses) {
appendListeners( type, resolveListenerInstances( type, listenerClasses ) );
}
@Override
public <T> void appendListeners(EventType<T> type, T... listeners) {
@SafeVarargs
public final <T> void appendListeners(EventType<T> type, T... listeners) {
getEventListenerGroup( type ).appendListeners( listeners );
}
@Override
public <T> void prependListeners(EventType<T> type, Class<? extends T>... listenerClasses) {
@SafeVarargs
public final <T> void prependListeners(EventType<T> type, Class<? extends T>... listenerClasses) {
prependListeners( type, resolveListenerInstances( type, listenerClasses ) );
}
@Override
public <T> void prependListeners(EventType<T> type, T... listeners) {
@SafeVarargs
public final <T> void prependListeners(EventType<T> type, T... listeners) {
getEventListenerGroup( type ).prependListeners( listeners );
}
private static EventListenerGroupImpl[] prepareListenerAssociation() {
private EventListenerGroupImpl[] buildListenerGroups(BootstrapContext bootstrapContext) {
EventListenerGroupImpl[] listenerArray = new EventListenerGroupImpl[ EventType.values().size() ];
// auto-flush listeners
@ -347,12 +399,14 @@ public class EventListenerRegistryImpl implements EventListenerRegistry {
// post-delete listeners
prepareListeners(
POST_DELETE,
new PostDeleteEventListenerStandardImpl(),
listenerArray
);
// post-insert listeners
prepareListeners(
POST_INSERT,
new PostInsertEventListenerStandardImpl(),
listenerArray
);
@ -366,6 +420,7 @@ public class EventListenerRegistryImpl implements EventListenerRegistry {
// post-update listeners
prepareListeners(
POST_UPDATE,
new PostUpdateEventListenerStandardImpl(),
listenerArray
);
@ -407,19 +462,19 @@ public class EventListenerRegistryImpl implements EventListenerRegistry {
return listenerArray;
}
private static <T> void prepareListeners(EventType<T> type, EventListenerGroupImpl[] listenerArray) {
private <T> void prepareListeners(EventType<T> type, EventListenerGroupImpl[] listenerArray) {
prepareListeners( type, null, listenerArray );
}
private static <T> void prepareListeners(EventType<T> type, T defaultListener, EventListenerGroupImpl[] listenerArray) {
private <T> void prepareListeners(EventType<T> type, T defaultListener, EventListenerGroupImpl[] listenerArray) {
final EventListenerGroupImpl<T> listenerGroup;
if ( type == EventType.POST_COMMIT_DELETE
|| type == EventType.POST_COMMIT_INSERT
|| type == EventType.POST_COMMIT_UPDATE ) {
listenerGroup = new PostCommitEventListenerGroupImpl<T>( type );
listenerGroup = new PostCommitEventListenerGroupImpl<T>( type, this );
}
else {
listenerGroup = new EventListenerGroupImpl<T>( type );
listenerGroup = new EventListenerGroupImpl<T>( type, this );
}
if ( defaultListener != null ) {
@ -428,4 +483,13 @@ public class EventListenerRegistryImpl implements EventListenerRegistry {
listenerArray[ type.ordinal() ] = listenerGroup;
}
@Override
public void stop() {
if ( callbackRegistry != null ) {
callbackRegistry.release();
}
if ( callbackBuilder != null ) {
callbackBuilder.release();
}
}
}

View File

@ -25,6 +25,6 @@ public class EventListenerServiceInitiator implements SessionFactoryServiceIniti
@Override
public EventListenerRegistry initiateService(SessionFactoryServiceInitiatorContext context) {
return new EventListenerRegistryImpl();
return new EventListenerRegistryImpl( context.getBootstrapContext(), context.getSessionFactory() );
}
}

View File

@ -22,13 +22,13 @@ import org.hibernate.internal.CoreMessageLogger;
*
* @author Steve Ebersole
*/
public class PostCommitEventListenerGroupImpl<T> extends EventListenerGroupImpl<T> {
class PostCommitEventListenerGroupImpl<T> extends EventListenerGroupImpl<T> {
private static final CoreMessageLogger log = CoreLogging.messageLogger( PostCommitEventListenerGroupImpl.class );
private final Class extendedListenerContract;
public PostCommitEventListenerGroupImpl(EventType<T> eventType) {
super( eventType );
public PostCommitEventListenerGroupImpl(EventType<T> eventType, EventListenerRegistryImpl listenerRegistry) {
super( eventType, listenerRegistry );
if ( eventType == EventType.POST_COMMIT_DELETE ) {
this.extendedListenerContract = PostCommitDeleteEventListener.class;

View File

@ -8,6 +8,7 @@ package org.hibernate.event.service.spi;
import java.io.Serializable;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.event.spi.EventType;
import org.hibernate.service.Service;
@ -18,16 +19,18 @@ import org.hibernate.service.Service;
* @author Steve Ebersole
*/
public interface EventListenerRegistry extends Service, Serializable {
public <T> EventListenerGroup<T> getEventListenerGroup(EventType<T> eventType);
void prepare(MetadataImplementor metadata);
public void addDuplicationStrategy(DuplicationStrategy strategy);
<T> EventListenerGroup<T> getEventListenerGroup(EventType<T> eventType);
public <T> void setListeners(EventType<T> type, Class<? extends T>... listeners);
public <T> void setListeners(EventType<T> type, T... listeners);
void addDuplicationStrategy(DuplicationStrategy strategy);
public <T> void appendListeners(EventType<T> type, Class<? extends T>... listeners);
public <T> void appendListeners(EventType<T> type, T... listeners);
<T> void setListeners(EventType<T> type, Class<? extends T>... listeners);
<T> void setListeners(EventType<T> type, T... listeners);
public <T> void prependListeners(EventType<T> type, Class<? extends T>... listeners);
public <T> void prependListeners(EventType<T> type, T... listeners);
<T> void appendListeners(EventType<T> type, Class<? extends T>... listeners);
<T> void appendListeners(EventType<T> type, T... listeners);
<T> void prependListeners(EventType<T> type, Class<? extends T>... listeners);
<T> void prependListeners(EventType<T> type, T... listeners);
}

View File

@ -4,12 +4,13 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.event.internal.core;
package org.hibernate.event.service.spi;
/**
* Marker interface for handling listener duplication checking (to avoid multiple registrations).
* Defines an event listener that is sensitive to whether a native or jpa bootstrap was performed
*
* @author Steve Ebersole
*/
public interface HibernateEntityManagerEventListener {
public interface JpaBootstrapSensitive {
void wasJpaBootstrap(boolean wasJpaBootstrap);
}

View File

@ -207,6 +207,8 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
.getService( SessionFactoryServiceRegistryFactory.class )
.buildServiceRegistry( this, bootstrapContext, options );
prepareEventListeners( metadata );
final CfgXmlAccessService cfgXmlAccessService = serviceRegistry.getService( CfgXmlAccessService.class );
String sfName = settings.getSessionFactoryName();
@ -388,6 +390,40 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
}
}
private void prepareEventListeners(MetadataImplementor metadata) {
final EventListenerRegistry eventListenerRegistry = serviceRegistry.getService( EventListenerRegistry.class );
final ConfigurationService cfgService = serviceRegistry.getService( ConfigurationService.class );
final ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
eventListenerRegistry.prepare( metadata );
for ( Map.Entry entry : ( (Map<?, ?>) cfgService.getSettings() ).entrySet() ) {
if ( !String.class.isInstance( entry.getKey() ) ) {
continue;
}
final String propertyName = (String) entry.getKey();
if ( !propertyName.startsWith( org.hibernate.jpa.AvailableSettings.EVENT_LISTENER_PREFIX ) ) {
continue;
}
final String eventTypeName = propertyName.substring( org.hibernate.jpa.AvailableSettings.EVENT_LISTENER_PREFIX
.length() + 1 );
final EventType eventType = EventType.resolveEventTypeByName( eventTypeName );
final EventListenerGroup eventListenerGroup = eventListenerRegistry.getEventListenerGroup( eventType );
for ( String listenerImpl : ( (String) entry.getValue() ).split( " ," ) ) {
eventListenerGroup.appendListener( instantiate( listenerImpl, classLoaderService ) );
}
}
}
private Object instantiate(String listenerImpl, ClassLoaderService classLoaderService) {
try {
return classLoaderService.classForName( listenerImpl ).newInstance();
}
catch (Exception e) {
throw new HibernateException( "Could not instantiate requested listener [" + listenerImpl + "]", e );
}
}
private void applyCfgXmlValues(LoadedConfig aggregatedConfig, SessionFactoryServiceRegistry serviceRegistry) {
final JaccService jaccService = serviceRegistry.getService( JaccService.class );
if ( jaccService.getContextId() != null ) {

View File

@ -36,7 +36,6 @@ import org.hibernate.boot.cfgxml.internal.ConfigLoader;
import org.hibernate.boot.cfgxml.spi.CfgXmlAccessService;
import org.hibernate.boot.cfgxml.spi.LoadedConfig;
import org.hibernate.boot.cfgxml.spi.MappingReference;
import org.hibernate.boot.model.TypeContributor;
import org.hibernate.boot.model.process.spi.ManagedResources;
import org.hibernate.boot.model.process.spi.MetadataBuildingProcess;
import org.hibernate.boot.registry.BootstrapServiceRegistry;
@ -68,7 +67,6 @@ import org.hibernate.jpa.boot.spi.IntegratorProvider;
import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor;
import org.hibernate.jpa.boot.spi.StrategyRegistrationProviderList;
import org.hibernate.jpa.boot.spi.TypeContributorList;
import org.hibernate.jpa.event.spi.JpaIntegrator;
import org.hibernate.jpa.internal.util.LogHelper;
import org.hibernate.jpa.internal.util.PersistenceUnitTransactionTypeHelper;
import org.hibernate.jpa.spi.IdentifierGeneratorStrategyProvider;
@ -334,8 +332,6 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
ClassLoaderService providedClassLoaderService) {
final BootstrapServiceRegistryBuilder bsrBuilder = new BootstrapServiceRegistryBuilder();
bsrBuilder.applyIntegrator( new JpaIntegrator() );
final IntegratorProvider integratorProvider = (IntegratorProvider) integrationSettings.get( INTEGRATOR_PROVIDER );
if ( integratorProvider != null ) {
for ( Integrator integrator : integratorProvider.getIntegrators() ) {
@ -772,9 +768,7 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
// add any explicit orm.xml references passed in
final List<String> explicitOrmXmlList = (List<String>) configurationValues.remove( AvailableSettings.XML_FILE_NAMES );
if ( explicitOrmXmlList != null ) {
for ( String ormXml : explicitOrmXmlList ) {
metadataSources.addResource( ormXml );
}
explicitOrmXmlList.forEach( metadataSources::addResource );
}
return attributeConverterDefinitions;
@ -800,24 +794,18 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
);
if ( mergedSettings.cacheRegionDefinitions != null ) {
for ( CacheRegionDefinition localCacheRegionDefinition : mergedSettings.cacheRegionDefinitions ) {
metamodelBuilder.applyCacheRegionDefinition( localCacheRegionDefinition );
}
mergedSettings.cacheRegionDefinitions.forEach( metamodelBuilder::applyCacheRegionDefinition );
}
final TypeContributorList typeContributorList = (TypeContributorList) configurationValues.remove(
TYPE_CONTRIBUTORS
);
if ( typeContributorList != null ) {
for ( TypeContributor typeContributor : typeContributorList.getTypeContributors() ) {
metamodelBuilder.applyTypes( typeContributor );
}
typeContributorList.getTypeContributors().forEach( metamodelBuilder::applyTypes );
}
if ( attributeConverterDefinitions != null ) {
for ( AttributeConverterDefinition attributeConverterDefinition : attributeConverterDefinitions ) {
metamodelBuilder.applyAttributeConverter( attributeConverterDefinition );
}
attributeConverterDefinitions.forEach( metamodelBuilder::applyAttributeConverter );
}
}
@ -903,7 +891,6 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
}
protected void populate(SessionFactoryBuilder sfBuilder, StandardServiceRegistry ssr) {
metamodelBuilder.getBootstrapContext().markAsJpaBootstrap();
final StrategySelector strategySelector = ssr.getService( StrategySelector.class );

View File

@ -4,7 +4,10 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.jpa.event.spi;
package org.hibernate.jpa.event.internal;
import org.hibernate.jpa.event.spi.Callback;
import org.hibernate.jpa.event.spi.CallbackType;
/**
* Abstract support for Callback implementations

View File

@ -76,6 +76,11 @@ public class CallbackBuilderLegacyImpl implements CallbackBuilder {
}
}
@Override
public void release() {
// nothing to do
}
@SuppressWarnings({"unchecked", "WeakerAccess"})
public Callback[] resolveCallbacks(XClass beanClass, CallbackType callbackType, ReflectionManager reflectionManager) {
List<Callback> callbacks = new ArrayList<>();

View File

@ -9,7 +9,6 @@ package org.hibernate.jpa.event.internal;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.hibernate.jpa.event.spi.AbstractCallback;
import org.hibernate.jpa.event.spi.CallbackType;
/**

View File

@ -9,7 +9,6 @@ package org.hibernate.jpa.event.internal;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.hibernate.jpa.event.spi.AbstractCallback;
import org.hibernate.jpa.event.spi.CallbackType;
import org.hibernate.resource.beans.spi.ManagedBean;

View File

@ -1,38 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.event.internal.core;
import java.util.IdentityHashMap;
import org.hibernate.engine.spi.CascadingAction;
import org.hibernate.engine.spi.CascadingActions;
import org.hibernate.event.internal.DefaultAutoFlushEventListener;
import org.hibernate.event.spi.AutoFlushEventListener;
/**
* In JPA, it is the create operation that is cascaded to unmanaged entities at flush time (instead of the save-update
* operation in Hibernate).
*
* @author Gavin King
*/
public class JpaAutoFlushEventListener
extends DefaultAutoFlushEventListener
implements HibernateEntityManagerEventListener {
public static final AutoFlushEventListener INSTANCE = new JpaAutoFlushEventListener();
@Override
protected CascadingAction getCascadingAction() {
return CascadingActions.PERSIST_ON_FLUSH;
}
@Override
protected Object getAnything() {
return new IdentityHashMap( 10 );
}
}

View File

@ -1,54 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.event.internal.core;
import java.io.Serializable;
import org.hibernate.event.internal.DefaultDeleteEventListener;
import org.hibernate.event.spi.DeleteEvent;
import org.hibernate.event.spi.EventSource;
import org.hibernate.jpa.event.spi.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.CallbackRegistry;
import org.hibernate.persister.entity.EntityPersister;
/**
* Overrides the LifeCycle OnSave call to call the PreRemove operation
*
* @author Emmanuel Bernard
*/
public class JpaDeleteEventListener extends DefaultDeleteEventListener implements CallbackRegistryConsumer {
private CallbackRegistry callbackRegistry;
public void injectCallbackRegistry(CallbackRegistry callbackRegistry) {
this.callbackRegistry = callbackRegistry;
}
public JpaDeleteEventListener() {
super();
}
public JpaDeleteEventListener(CallbackRegistry callbackRegistry) {
this();
this.callbackRegistry = callbackRegistry;
}
@Override
protected boolean invokeDeleteLifecycle(EventSource session, Object entity, EntityPersister persister) {
callbackRegistry.preRemove( entity );
return super.invokeDeleteLifecycle( session, entity, persister );
}
@Override
protected void performDetachedEntityDeletionCheck(DeleteEvent event) {
EventSource source = event.getSession();
String entityName = event.getEntityName();
EntityPersister persister = source.getEntityPersister( entityName, event.getObject() );
Serializable id = persister.getIdentifier( event.getObject(), source );
entityName = entityName == null ? source.guessEntityName( event.getObject() ) : entityName;
throw new IllegalArgumentException("Removing a detached instance "+ entityName + "#" + id);
}
}

View File

@ -1,74 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.event.internal.core;
import org.hibernate.SessionFactory;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.Status;
import org.hibernate.event.internal.DefaultFlushEntityEventListener;
import org.hibernate.jpa.event.spi.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.CallbackRegistry;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.Type;
/**
* Overrides the LifeCycle OnSave call to call the PreUpdate operation
*
* @author Emmanuel Bernard
*/
public class JpaFlushEntityEventListener extends DefaultFlushEntityEventListener implements CallbackRegistryConsumer {
private CallbackRegistry callbackRegistry;
public void injectCallbackRegistry(CallbackRegistry callbackRegistry) {
this.callbackRegistry = callbackRegistry;
}
public JpaFlushEntityEventListener() {
super();
}
public JpaFlushEntityEventListener(CallbackRegistry callbackRegistry) {
super();
this.callbackRegistry = callbackRegistry;
}
@Override
protected boolean invokeInterceptor(
SessionImplementor session,
Object entity,
EntityEntry entry,
Object[] values,
EntityPersister persister) {
boolean isDirty = false;
if ( entry.getStatus() != Status.DELETED ) {
if ( callbackRegistry.preUpdate( entity ) ) {
isDirty = copyState( entity, persister.getPropertyTypes(), values, session.getFactory() );
}
}
return super.invokeInterceptor( session, entity, entry, values, persister ) || isDirty;
}
private boolean copyState(Object entity, Type[] types, Object[] state, SessionFactory sf) {
// copy the entity state into the state array and return true if the state has changed
ClassMetadata metadata = sf.getClassMetadata( entity.getClass() );
Object[] newState = metadata.getPropertyValues( entity );
int size = newState.length;
boolean isDirty = false;
for ( int index = 0; index < size ; index++ ) {
if ( ( state[index] == LazyPropertyInitializer.UNFETCHED_PROPERTY &&
newState[index] != LazyPropertyInitializer.UNFETCHED_PROPERTY ) ||
( state[index] != newState[index] && !types[index].isEqual( state[index], newState[index] ) ) ) {
isDirty = true;
state[index] = newState[index];
}
}
return isDirty;
}
}

View File

@ -1,35 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.event.internal.core;
import java.util.IdentityHashMap;
import org.hibernate.engine.spi.CascadingAction;
import org.hibernate.engine.spi.CascadingActions;
import org.hibernate.event.internal.DefaultFlushEventListener;
import org.hibernate.event.spi.FlushEventListener;
/**
* In JPA, it is the create operation that is cascaded to unmanaged entities at flush time (instead of the
* save-update operation in Hibernate).
*
* @author Gavin King
*/
public class JpaFlushEventListener extends DefaultFlushEventListener implements HibernateEntityManagerEventListener {
public static final FlushEventListener INSTANCE = new JpaFlushEventListener();
@Override
protected CascadingAction getCascadingAction() {
return CascadingActions.PERSIST_ON_FLUSH;
}
@Override
protected Object getAnything() {
return new IdentityHashMap( 10 );
}
}

View File

@ -1,58 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.event.internal.core;
import java.io.Serializable;
import org.hibernate.event.internal.DefaultMergeEventListener;
import org.hibernate.event.spi.EventSource;
import org.hibernate.jpa.event.spi.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.CallbackRegistry;
/**
* Overrides the LifeCycle OnSave call to call the PrePersist operation
*
* @author Emmanuel Bernard
*/
public class JpaMergeEventListener extends DefaultMergeEventListener implements CallbackRegistryConsumer {
private CallbackRegistry callbackRegistry;
public void injectCallbackRegistry(CallbackRegistry callbackRegistry) {
this.callbackRegistry = callbackRegistry;
}
public JpaMergeEventListener() {
super();
}
public JpaMergeEventListener(CallbackRegistry callbackRegistry) {
super();
this.callbackRegistry = callbackRegistry;
}
@Override
protected Serializable saveWithRequestedId(
Object entity,
Serializable requestedId,
String entityName,
Object anything,
EventSource source) {
callbackRegistry.preCreate( entity );
return super.saveWithRequestedId( entity, requestedId, entityName, anything, source );
}
@Override
protected Serializable saveWithGeneratedId(
Object entity,
String entityName,
Object anything,
EventSource source,
boolean requiresImmediateIdAccess) {
callbackRegistry.preCreate( entity );
return super.saveWithGeneratedId( entity, entityName, anything, source, requiresImmediateIdAccess );
}
}

View File

@ -1,100 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.event.internal.core;
import java.io.Serializable;
import java.util.Iterator;
import java.util.Map;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.CascadingAction;
import org.hibernate.engine.spi.CascadingActions;
import org.hibernate.event.internal.DefaultPersistEventListener;
import org.hibernate.event.spi.EventSource;
import org.hibernate.jpa.event.spi.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.CallbackRegistry;
import org.hibernate.type.CollectionType;
import org.jboss.logging.Logger;
/**
* Overrides the LifeCycle OnSave call to call the PrePersist operation
*
* @author Emmanuel Bernard
*/
public class JpaPersistEventListener extends DefaultPersistEventListener implements CallbackRegistryConsumer {
private static final Logger log = Logger.getLogger( JpaPersistEventListener.class );
private CallbackRegistry callbackRegistry;
@Override
public void injectCallbackRegistry(CallbackRegistry callbackRegistry) {
this.callbackRegistry = callbackRegistry;
}
public JpaPersistEventListener() {
super();
}
public JpaPersistEventListener(CallbackRegistry callbackRegistry) {
super();
this.callbackRegistry = callbackRegistry;
}
@Override
protected Serializable saveWithRequestedId(
Object entity,
Serializable requestedId,
String entityName,
Object anything,
EventSource source) {
callbackRegistry.preCreate( entity );
return super.saveWithRequestedId( entity, requestedId, entityName, anything, source );
}
@Override
protected Serializable saveWithGeneratedId(
Object entity,
String entityName,
Object anything,
EventSource source,
boolean requiresImmediateIdAccess) {
callbackRegistry.preCreate( entity );
return super.saveWithGeneratedId( entity, entityName, anything, source, requiresImmediateIdAccess );
}
@Override
protected CascadingAction getCascadeAction() {
return PERSIST_SKIPLAZY;
}
public static final CascadingAction PERSIST_SKIPLAZY = new CascadingActions.BaseCascadingAction() {
@Override
public void cascade(EventSource session, Object child, String entityName, Object anything, boolean isCascadeDeleteEnabled)
throws HibernateException {
log.trace( "Cascading persist to : " + entityName );
session.persist( entityName, child, (Map) anything );
}
@Override
public Iterator getCascadableChildrenIterator(EventSource session, CollectionType collectionType, Object collection) {
// persists don't cascade to uninitialized collections
return CascadingActions.getLoadedElementsIterator( session, collectionType, collection );
}
@Override
public boolean deleteOrphans() {
return false;
}
@Override
public boolean performOnLazyProperty() {
return false;
}
@Override
public String toString() {
return "ACTION_PERSIST_SKIPLAZY";
}
};
}

View File

@ -1,20 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.event.internal.core;
import org.hibernate.engine.spi.CascadingAction;
import org.hibernate.engine.spi.CascadingActions;
/**
* @author Emmanuel Bernard
*/
public class JpaPersistOnFlushEventListener extends JpaPersistEventListener {
@Override
protected CascadingAction getCascadeAction() {
return CascadingActions.PERSIST_ON_FLUSH;
}
}

View File

@ -1,39 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.event.internal.core;
import org.hibernate.event.spi.PostLoadEvent;
import org.hibernate.event.spi.PostLoadEventListener;
import org.hibernate.jpa.event.spi.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.CallbackRegistry;
/**
* @author <a href="mailto:kabir.khan@jboss.org">Kabir Khan</a>
*/
public class JpaPostLoadEventListener implements PostLoadEventListener, CallbackRegistryConsumer {
CallbackRegistry callbackRegistry;
@Override
public void injectCallbackRegistry(CallbackRegistry callbackRegistry) {
this.callbackRegistry = callbackRegistry;
}
public JpaPostLoadEventListener() {
super();
}
public JpaPostLoadEventListener(CallbackRegistry callbackRegistry) {
this.callbackRegistry = callbackRegistry;
}
@Override
public void onPostLoad(PostLoadEvent event) {
Object entity = event.getEntity();
callbackRegistry.postLoad( entity );
}
}

View File

@ -1,89 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.event.internal.core;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.Status;
import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.PostCollectionRecreateEvent;
import org.hibernate.event.spi.PostCollectionRecreateEventListener;
import org.hibernate.event.spi.PostCollectionRemoveEvent;
import org.hibernate.event.spi.PostCollectionRemoveEventListener;
import org.hibernate.event.spi.PostCollectionUpdateEvent;
import org.hibernate.event.spi.PostCollectionUpdateEventListener;
import org.hibernate.event.spi.PostUpdateEvent;
import org.hibernate.event.spi.PostUpdateEventListener;
import org.hibernate.jpa.event.spi.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.CallbackRegistry;
import org.hibernate.jpa.event.spi.CallbackType;
import org.hibernate.persister.entity.EntityPersister;
/**
* Implementation of the post update listeners.
*
* @author <a href="mailto:kabir.khan@jboss.org">Kabir Khan</a>
*/
@SuppressWarnings("serial")
public class JpaPostUpdateEventListener
implements PostUpdateEventListener, CallbackRegistryConsumer, PostCollectionRecreateEventListener,
PostCollectionRemoveEventListener, PostCollectionUpdateEventListener {
private CallbackRegistry callbackRegistry;
@Override
public void injectCallbackRegistry(CallbackRegistry callbackRegistry) {
this.callbackRegistry = callbackRegistry;
}
public JpaPostUpdateEventListener() {
super();
}
public JpaPostUpdateEventListener(CallbackRegistry callbackRegistry) {
this.callbackRegistry = callbackRegistry;
}
@Override
public void onPostUpdate(PostUpdateEvent event) {
Object entity = event.getEntity();
EventSource eventSource = event.getSession();
handlePostUpdate(entity, eventSource);
}
private void handlePostUpdate(Object entity, EventSource source) {
EntityEntry entry = (EntityEntry) source.getPersistenceContext().getEntry( entity );
// mimic the preUpdate filter
if ( Status.DELETED != entry.getStatus()) {
callbackRegistry.postUpdate(entity);
}
}
@Override
public boolean requiresPostCommitHanding(EntityPersister persister) {
return callbackRegistry.hasRegisteredCallbacks( persister.getMappedClass(), CallbackType.POST_UPDATE );
}
@Override
public void onPostRecreateCollection(PostCollectionRecreateEvent event) {
Object entity = event.getCollection().getOwner();
EventSource eventSource = event.getSession();
handlePostUpdate(entity, eventSource);
}
@Override
public void onPostRemoveCollection(PostCollectionRemoveEvent event) {
Object entity = event.getCollection().getOwner();
EventSource eventSource = event.getSession();
handlePostUpdate(entity, eventSource);
}
@Override
public void onPostUpdateCollection(PostCollectionUpdateEvent event) {
Object entity = event.getCollection().getOwner();
EventSource eventSource = event.getSession();
handlePostUpdate(entity, eventSource);
}
}

View File

@ -1,58 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.event.internal.core;
import java.io.Serializable;
import org.hibernate.event.internal.DefaultSaveEventListener;
import org.hibernate.event.spi.EventSource;
import org.hibernate.jpa.event.spi.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.CallbackRegistry;
/**
* Overrides the LifeCycle OnSave call to call the PrePersist operation
*
* @author Emmanuel Bernard
*/
public class JpaSaveEventListener extends DefaultSaveEventListener implements CallbackRegistryConsumer {
private CallbackRegistry callbackRegistry;
public void injectCallbackRegistry(CallbackRegistry callbackRegistry) {
this.callbackRegistry = callbackRegistry;
}
public JpaSaveEventListener() {
super();
}
public JpaSaveEventListener(CallbackRegistry callbackRegistry) {
super();
this.callbackRegistry = callbackRegistry;
}
@Override
protected Serializable saveWithRequestedId(
Object entity,
Serializable requestedId,
String entityName,
Object anything,
EventSource source) {
callbackRegistry.preCreate( entity );
return super.saveWithRequestedId( entity, requestedId, entityName, anything, source );
}
@Override
protected Serializable saveWithGeneratedId(
Object entity,
String entityName,
Object anything,
EventSource source,
boolean requiresImmediateIdAccess) {
callbackRegistry.preCreate( entity );
return super.saveWithGeneratedId( entity, entityName, anything, source, requiresImmediateIdAccess );
}
}

View File

@ -1,58 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.event.internal.core;
import java.io.Serializable;
import org.hibernate.event.internal.DefaultSaveOrUpdateEventListener;
import org.hibernate.event.spi.EventSource;
import org.hibernate.jpa.event.spi.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.CallbackRegistry;
/**
* Overrides the LifeCycle OnSave call to call the PrePersist operation
*
* @author Emmanuel Bernard
*/
public class JpaSaveOrUpdateEventListener extends DefaultSaveOrUpdateEventListener implements CallbackRegistryConsumer {
private CallbackRegistry callbackRegistry;
public void injectCallbackRegistry(CallbackRegistry callbackRegistry) {
this.callbackRegistry = callbackRegistry;
}
public JpaSaveOrUpdateEventListener() {
super();
}
public JpaSaveOrUpdateEventListener(CallbackRegistry callbackRegistry) {
super();
this.callbackRegistry = callbackRegistry;
}
@Override
protected Serializable saveWithRequestedId(
Object entity,
Serializable requestedId,
String entityName,
Object anything,
EventSource source) {
callbackRegistry.preCreate( entity );
return super.saveWithRequestedId( entity, requestedId, entityName, anything, source );
}
@Override
protected Serializable saveWithGeneratedId(
Object entity,
String entityName,
Object anything,
EventSource source,
boolean requiresImmediateIdAccess) {
callbackRegistry.preCreate( entity );
return super.saveWithGeneratedId( entity, entityName, anything, source, requiresImmediateIdAccess );
}
}

View File

@ -1,15 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.event.internal.core;
/**
* Hibernate EntityManager specific implementations of Hibernate event listeners. Generally the listeners
* here either:<ul>
* <li>provide tweaks to internal processing to conform with JPA spec</li>
* <li>bridge to JPA event callbacks</li>
* </ul>
*/

View File

@ -0,0 +1,12 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
/**
* Internal details of implementing support for JPA callbacks
*/
package org.hibernate.jpa.event.internal;

View File

@ -0,0 +1,11 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
/**
* Support for JPA lifecycle callbacks.
*/
package org.hibernate.jpa.event;

View File

@ -27,4 +27,6 @@ public interface CallbackBuilder {
}
void buildCallbacksForEntity(String entityName, CallbackRegistrar callbackRegistrar);
void release();
}

View File

@ -6,15 +6,13 @@
*/
package org.hibernate.jpa.event.spi;
import org.hibernate.jpa.event.internal.core.HibernateEntityManagerEventListener;
/**
* Contract for injecting the registry of Callbacks into event listeners.
*
* @author Emmanuel Bernard
* @author Steve Ebersole
*/
public interface CallbackRegistryConsumer extends HibernateEntityManagerEventListener {
public interface CallbackRegistryConsumer {
/**
* Injection of the CallbackRegistry
*

View File

@ -1,206 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.event.spi;
import java.util.Map;
import org.hibernate.HibernateException;
import org.hibernate.annotations.common.reflection.ReflectionManager;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.internal.MetadataImpl;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.CascadeStyles;
import org.hibernate.engine.spi.CascadingAction;
import org.hibernate.engine.spi.CascadingActions;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.event.service.spi.DuplicationStrategy;
import org.hibernate.event.service.spi.EventListenerGroup;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventType;
import org.hibernate.integrator.spi.Integrator;
import org.hibernate.jpa.AvailableSettings;
import org.hibernate.jpa.event.internal.CallbackBuilderLegacyImpl;
import org.hibernate.jpa.event.internal.CallbackRegistryImpl;
import org.hibernate.jpa.event.internal.core.HibernateEntityManagerEventListener;
import org.hibernate.jpa.event.internal.core.JpaAutoFlushEventListener;
import org.hibernate.jpa.event.internal.core.JpaDeleteEventListener;
import org.hibernate.jpa.event.internal.core.JpaFlushEntityEventListener;
import org.hibernate.jpa.event.internal.core.JpaFlushEventListener;
import org.hibernate.jpa.event.internal.core.JpaMergeEventListener;
import org.hibernate.jpa.event.internal.core.JpaPersistEventListener;
import org.hibernate.jpa.event.internal.core.JpaPersistOnFlushEventListener;
import org.hibernate.jpa.event.internal.core.JpaPostDeleteEventListener;
import org.hibernate.jpa.event.internal.core.JpaPostInsertEventListener;
import org.hibernate.jpa.event.internal.core.JpaPostLoadEventListener;
import org.hibernate.jpa.event.internal.core.JpaPostUpdateEventListener;
import org.hibernate.jpa.event.internal.core.JpaSaveEventListener;
import org.hibernate.jpa.event.internal.core.JpaSaveOrUpdateEventListener;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
/**
* Hibernate EntityManager specific Integrator, performing JPA setup.
*
* @author Steve Ebersole
*/
public class JpaIntegrator implements Integrator {
private CallbackRegistryImpl callbackRegistry;
private CascadeStyle oldPersistCascadeStyle;
private static final DuplicationStrategy JPA_DUPLICATION_STRATEGY = new JPADuplicationStrategy();
/**
* Perform integration.
*
* @param metadata The "compiled" representation of the mapping information
* @param sessionFactory The session factory being created
* @param serviceRegistry The session factory's service registry
*/
public void integrate(
Metadata metadata,
SessionFactoryImplementor sessionFactory,
SessionFactoryServiceRegistry serviceRegistry) {
// first, register the JPA-specific persist cascade style
try {
oldPersistCascadeStyle = CascadeStyles.getCascadeStyle( "persist" );
}
catch (Exception e) {
}
CascadeStyles.registerCascadeStyle(
"persist",
new PersistCascadeStyle()
);
// then prepare listeners
final EventListenerRegistry eventListenerRegistry = serviceRegistry.getService( EventListenerRegistry.class );
eventListenerRegistry.addDuplicationStrategy( JPA_DUPLICATION_STRATEGY );
// op listeners
eventListenerRegistry.setListeners( EventType.AUTO_FLUSH, JpaAutoFlushEventListener.INSTANCE );
eventListenerRegistry.setListeners( EventType.DELETE, new JpaDeleteEventListener() );
eventListenerRegistry.setListeners( EventType.FLUSH_ENTITY, new JpaFlushEntityEventListener() );
eventListenerRegistry.setListeners( EventType.FLUSH, JpaFlushEventListener.INSTANCE );
eventListenerRegistry.setListeners( EventType.MERGE, new JpaMergeEventListener() );
eventListenerRegistry.setListeners( EventType.PERSIST, new JpaPersistEventListener() );
eventListenerRegistry.setListeners( EventType.PERSIST_ONFLUSH, new JpaPersistOnFlushEventListener() );
eventListenerRegistry.setListeners( EventType.SAVE, new JpaSaveEventListener() );
eventListenerRegistry.setListeners( EventType.SAVE_UPDATE, new JpaSaveOrUpdateEventListener() );
// post op listeners
eventListenerRegistry.prependListeners( EventType.POST_DELETE, new JpaPostDeleteEventListener() );
eventListenerRegistry.prependListeners( EventType.POST_INSERT, new JpaPostInsertEventListener() );
eventListenerRegistry.prependListeners( EventType.POST_LOAD, new JpaPostLoadEventListener() );
eventListenerRegistry.prependListeners( EventType.POST_UPDATE, new JpaPostUpdateEventListener() );
final ConfigurationService cfgService = serviceRegistry.getService( ConfigurationService.class );
for ( Map.Entry entry : ( (Map<?, ?>) cfgService.getSettings() ).entrySet() ) {
if ( !String.class.isInstance( entry.getKey() ) ) {
continue;
}
final String propertyName = (String) entry.getKey();
if ( !propertyName.startsWith( AvailableSettings.EVENT_LISTENER_PREFIX ) ) {
continue;
}
final String eventTypeName = propertyName.substring( AvailableSettings.EVENT_LISTENER_PREFIX.length() + 1 );
final EventType eventType = EventType.resolveEventTypeByName( eventTypeName );
final EventListenerGroup eventListenerGroup = eventListenerRegistry.getEventListenerGroup( eventType );
for ( String listenerImpl : ( (String) entry.getValue() ).split( " ," ) ) {
eventListenerGroup.appendListener( instantiate( listenerImpl, serviceRegistry ) );
}
}
// handle JPA "entity listener classes"...
this.callbackRegistry = new CallbackRegistryImpl();
final CallbackBuilder callbackBuilder = new CallbackBuilderLegacyImpl(
serviceRegistry.getService( ManagedBeanRegistry.class ),
//bootstrapContext.getReflectionManager()
null
);
for ( PersistentClass persistentClass : metadata.getEntityBindings() ) {
if ( persistentClass.getClassName() == null ) {
// we can have non java class persisted by hibernate
continue;
}
callbackBuilder.buildCallbacksForEntity( persistentClass.getClassName(), callbackRegistry );
}
for ( EventType eventType : EventType.values() ) {
final EventListenerGroup eventListenerGroup = eventListenerRegistry.getEventListenerGroup( eventType );
for ( Object listener : eventListenerGroup.listeners() ) {
if ( CallbackRegistryConsumer.class.isInstance( listener ) ) {
( (CallbackRegistryConsumer) listener ).injectCallbackRegistry( callbackRegistry );
}
}
}
}
@Override
public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
if ( oldPersistCascadeStyle == null ) {
CascadeStyles.registerCascadeStyle(
"persist",
null
);
}
CascadeStyles.registerCascadeStyle(
"persist",
(CascadeStyles.BaseCascadeStyle) oldPersistCascadeStyle
);
if ( callbackRegistry != null ) {
callbackRegistry.release();
}
}
private Object instantiate(String listenerImpl, ServiceRegistryImplementor serviceRegistry) {
try {
return serviceRegistry.getService( ClassLoaderService.class ).classForName( listenerImpl ).newInstance();
}
catch (Exception e) {
throw new HibernateException( "Could not instantiate requested listener [" + listenerImpl + "]", e );
}
}
private static class PersistCascadeStyle extends CascadeStyles.BaseCascadeStyle {
@Override
public boolean doCascade(CascadingAction action) {
return action == JpaPersistEventListener.PERSIST_SKIPLAZY
|| action == CascadingActions.PERSIST_ON_FLUSH;
}
@Override
public String toString() {
return "STYLE_PERSIST_SKIPLAZY";
}
}
private static class JPADuplicationStrategy implements DuplicationStrategy {
@Override
public boolean areMatch(Object listener, Object original) {
return listener.getClass().equals( original.getClass() ) &&
HibernateEntityManagerEventListener.class.isInstance( original );
}
@Override
public Action getAction() {
return Action.KEEP_ORIGINAL;
}
}
}

View File

@ -0,0 +1,12 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
/**
* The SPI contracts for supporting JPA lifecycle callbacks.
*/
package org.hibernate.jpa.event.spi;

View File

@ -25,7 +25,6 @@ import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jpa.event.spi.JpaIntegrator;
import org.hibernate.tool.schema.Action;
import org.junit.Test;
@ -51,9 +50,7 @@ public class BasicCdiTest {
count = 0;
try ( final SeContainer cdiContainer = cdiInitializer.initialize() ) {
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder()
.applyIntegrator( new JpaIntegrator() )
.build();
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder().build();
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder( bsr )
.applySetting( AvailableSettings.CDI_BEAN_MANAGER, cdiContainer.getBeanManager() )

View File

@ -8,11 +8,12 @@ package org.hibernate.test.bytecode.enhancement.lazy;
import org.hibernate.HibernateException;
import org.hibernate.bytecode.enhance.spi.UnloadedClass;
import org.hibernate.event.internal.DefaultFlushEventListener;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.LoadEvent;
import org.hibernate.event.spi.LoadEventListener;
import org.hibernate.jpa.event.internal.core.JpaFlushEventListener;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext;
@ -63,7 +64,6 @@ public class LazyProxyOnEnhancedEntityTest extends BaseCoreFunctionalTestCase {
@Test
public void test() {
EventListenerRegistry registry = sessionFactory().getServiceRegistry().getService( EventListenerRegistry.class );
registry.prependListeners( EventType.FLUSH, new JpaFlushEventListener() );
registry.prependListeners( EventType.LOAD, new ImmediateLoadTrap() );
doInJPA( this::sessionFactory, em -> {

View File

@ -16,7 +16,6 @@ import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jpa.event.spi.JpaIntegrator;
import org.hibernate.tool.schema.Action;
import org.hibernate.testing.junit4.BaseUnitTestCase;
@ -43,9 +42,7 @@ public class DelayedCdiHostedConverterTest extends BaseUnitTestCase {
.disableDiscovery()
.addBeanClasses( MonitorBean.class, ConverterBean.class );
try ( final SeContainer cdiContainer = cdiInitializer.initialize() ) {
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder()
.applyIntegrator( new JpaIntegrator() )
.build();
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder().build();
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder( bsr )
.applySetting( AvailableSettings.HBM2DDL_AUTO, Action.CREATE_DROP )

View File

@ -16,7 +16,6 @@ import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jpa.event.spi.JpaIntegrator;
import org.hibernate.tool.schema.Action;
import org.hibernate.testing.junit4.BaseUnitTestCase;
@ -42,9 +41,7 @@ public class CdiHostedConverterTest extends BaseUnitTestCase {
.disableDiscovery()
.addBeanClasses( MonitorBean.class, ConverterBean.class );
try ( final SeContainer cdiContainer = cdiInitializer.initialize() ) {
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder()
.applyIntegrator( new JpaIntegrator() )
.build();
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder().build();
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder( bsr )
.applySetting( AvailableSettings.HBM2DDL_AUTO, Action.CREATE_DROP )

View File

@ -16,7 +16,6 @@ import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jpa.event.spi.JpaIntegrator;
import org.hibernate.tool.schema.Action;
import org.hibernate.testing.junit4.BaseUnitTestCase;
@ -46,9 +45,7 @@ public class DelayedCdiSupportTest extends BaseUnitTestCase {
.disableDiscovery()
.addBeanClasses( Monitor.class, TheListener.class );
try ( final SeContainer cdiContainer = cdiInitializer.initialize() ) {
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder()
.applyIntegrator( new JpaIntegrator() )
.build();
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder().build();
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder( bsr )
.applySetting( AvailableSettings.HBM2DDL_AUTO, Action.CREATE_DROP )

View File

@ -13,7 +13,6 @@ import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jpa.event.spi.JpaIntegrator;
import org.hibernate.jpa.event.spi.jpa.ExtendedBeanManager;
import org.hibernate.tool.schema.Action;
@ -40,9 +39,7 @@ public class InvalidExtendedCdiSupportTest extends BaseUnitTestCase {
final ExtendedBeanManagerImpl standIn = new ExtendedBeanManagerImpl();
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder()
.applyIntegrator( new JpaIntegrator() )
.build();
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder().build();
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder( bsr )
.applySetting( AvailableSettings.HBM2DDL_AUTO, Action.CREATE_DROP )

View File

@ -17,7 +17,6 @@ import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jpa.event.spi.JpaIntegrator;
import org.hibernate.jpa.event.spi.jpa.ExtendedBeanManager;
import org.hibernate.tool.schema.Action;
@ -47,9 +46,7 @@ public class ValidExtendedCdiSupportTest extends BaseUnitTestCase {
final ExtendedBeanManagerImpl standIn = new ExtendedBeanManagerImpl();
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder()
.applyIntegrator( new JpaIntegrator() )
.build();
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder().build();
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder( bsr )
.applySetting( AvailableSettings.HBM2DDL_AUTO, Action.CREATE_DROP )

View File

@ -14,7 +14,6 @@ import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jpa.event.spi.JpaIntegrator;
import org.hibernate.tool.schema.Action;
import org.hibernate.testing.junit4.BaseUnitTestCase;
@ -36,9 +35,7 @@ public class InvalidNoCdiSupportTest extends BaseUnitTestCase {
public void testIt() {
Monitor.reset();
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder()
.applyIntegrator( new JpaIntegrator() )
.build();
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder().build();
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder( bsr )
.applySetting( AvailableSettings.HBM2DDL_AUTO, Action.CREATE_DROP )

View File

@ -20,11 +20,9 @@ import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jpa.event.spi.JpaIntegrator;
import org.hibernate.tool.schema.Action;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.hibernate.test.cdi.events.Monitor;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil2.inTransaction;
@ -43,9 +41,7 @@ public class ValidNoCdiSupportTest extends BaseUnitTestCase {
public void testIt() {
AnotherListener.reset();
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder()
.applyIntegrator( new JpaIntegrator() )
.build();
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder().build();
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder( bsr )
.applySetting( AvailableSettings.HBM2DDL_AUTO, Action.CREATE_DROP )

View File

@ -16,7 +16,6 @@ import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jpa.event.spi.JpaIntegrator;
import org.hibernate.tool.schema.Action;
import org.hibernate.testing.junit4.BaseUnitTestCase;
@ -45,9 +44,7 @@ public class StandardCdiSupportTest extends BaseUnitTestCase {
.disableDiscovery()
.addBeanClasses( Monitor.class, TheListener.class );
try ( final SeContainer cdiContainer = cdiInitializer.initialize() ) {
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder()
.applyIntegrator( new JpaIntegrator() )
.build();
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder().build();
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder( bsr )
.applySetting( AvailableSettings.HBM2DDL_AUTO, Action.CREATE_DROP )

View File

@ -13,7 +13,6 @@ import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.jpa.event.spi.JpaIntegrator;
import org.hibernate.resource.beans.container.internal.CdiBeanContainerBuilder;
import org.hibernate.resource.beans.container.internal.CdiBeanContainerDelayedAccessImpl;
import org.hibernate.resource.beans.container.spi.BeanContainer;
@ -44,9 +43,7 @@ public class DelayedMixedAccessTest implements BeanContainer.LifecycleOptions {
@Test
public void testDelayedMixedAccess() {
try ( final SeContainer cdiContainer = Helper.createSeContainer() ) {
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder()
.applyIntegrator( new JpaIntegrator() )
.build();
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder().build();
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder( bsr )
.applySetting( AvailableSettings.HBM2DDL_AUTO, Action.CREATE_DROP )

View File

@ -13,10 +13,8 @@ import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.jpa.event.spi.JpaIntegrator;
import org.hibernate.resource.beans.container.internal.CdiBeanContainerBuilder;
import org.hibernate.resource.beans.container.internal.CdiBeanContainerImmediateAccessImpl;
import org.hibernate.resource.beans.container.internal.JpaCompliantLifecycleStrategy;
import org.hibernate.resource.beans.container.spi.BeanContainer;
import org.hibernate.resource.beans.container.spi.ContainedBean;
import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer;
@ -47,9 +45,7 @@ public class ImmediateMixedAccessTests implements BeanContainer.LifecycleOptions
@Test
public void testImmediateMixedAccess() {
try ( final SeContainer cdiContainer = Helper.createSeContainer() ) {
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder()
.applyIntegrator( new JpaIntegrator() )
.build();
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder().build();
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder( bsr )
.applySetting( AvailableSettings.HBM2DDL_AUTO, Action.CREATE_DROP )

View File

@ -17,7 +17,6 @@ import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jpa.event.spi.JpaIntegrator;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.tool.schema.Action;
@ -170,7 +169,6 @@ public class NonRegistryManagedDelayedCdiSupportTest extends BaseUnitTestCase {
private SessionFactoryImplementor buildSessionFactory(SeContainer cdiContainer,
NonRegistryManagedBeanConsumingIntegrator beanConsumingIntegrator) {
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder()
.applyIntegrator( new JpaIntegrator() )
.applyIntegrator( beanConsumingIntegrator )
.build();

View File

@ -18,7 +18,6 @@ import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jpa.event.spi.JpaIntegrator;
import org.hibernate.jpa.event.spi.jpa.ExtendedBeanManager;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.tool.schema.Action;
@ -168,7 +167,6 @@ public class NonRegistryManagedExtendedCdiSupportTest extends BaseUnitTestCase {
private SessionFactoryImplementor buildSessionFactory(ExtendedBeanManagerImpl standIn,
NonRegistryManagedBeanConsumingIntegrator beanConsumingIntegrator) {
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder()
.applyIntegrator( new JpaIntegrator() )
.applyIntegrator( beanConsumingIntegrator )
.build();

View File

@ -17,7 +17,6 @@ import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jpa.event.spi.JpaIntegrator;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.tool.schema.Action;
@ -169,7 +168,6 @@ public class NonRegistryManagedStandardCdiSupportTest extends BaseUnitTestCase {
private SessionFactoryImplementor buildSessionFactory(SeContainer cdiContainer,
NonRegistryManagedBeanConsumingIntegrator beanConsumingIntegrator) {
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder()
.applyIntegrator( new JpaIntegrator() )
.applyIntegrator( beanConsumingIntegrator )
.build();