introduce Contexts for the other cascading operations that need them

and typesafety, finally!
This commit is contained in:
Gavin King 2022-01-30 14:06:26 +01:00
parent 7570d15291
commit 1b0862babd
27 changed files with 381 additions and 233 deletions

View File

@ -8,7 +8,6 @@ package org.hibernate.engine.internal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -21,6 +20,7 @@ import org.hibernate.engine.spi.CollectionEntry;
import org.hibernate.engine.spi.EntityEntry; import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.Status; import org.hibernate.engine.spi.Status;
import org.hibernate.event.spi.DeleteContext;
import org.hibernate.event.spi.EventSource; import org.hibernate.event.spi.EventSource;
import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
@ -56,8 +56,8 @@ public final class Cascade {
* @param persister The parent's entity persister * @param persister The parent's entity persister
* @param parent The parent reference. * @param parent The parent reference.
*/ */
public static void cascade( public static <T> void cascade(
final CascadingAction action, final CascadePoint cascadePoint, final CascadingAction<T> action, final CascadePoint cascadePoint,
final EventSource eventSource, final EntityPersister persister, final Object parent) final EventSource eventSource, final EntityPersister persister, final Object parent)
throws HibernateException { throws HibernateException {
cascade( action, cascadePoint, eventSource, persister, parent, null ); cascade( action, cascadePoint, eventSource, persister, parent, null );
@ -72,13 +72,13 @@ public final class Cascade {
* @param anything Anything ;) Typically some form of cascade-local cache * @param anything Anything ;) Typically some form of cascade-local cache
* which is specific to each CascadingAction type * which is specific to each CascadingAction type
*/ */
public static void cascade( public static <T> void cascade(
final CascadingAction action, final CascadingAction<T> action,
final CascadePoint cascadePoint, final CascadePoint cascadePoint,
final EventSource eventSource, final EventSource eventSource,
final EntityPersister persister, final EntityPersister persister,
final Object parent, final Object parent,
final Object anything) throws HibernateException { final T anything) throws HibernateException {
if ( persister.hasCascades() || action.requiresNoCascadeChecking() ) { // performance opt if ( persister.hasCascades() || action.requiresNoCascadeChecking() ) { // performance opt
final boolean traceEnabled = LOG.isTraceEnabled(); final boolean traceEnabled = LOG.isTraceEnabled();
@ -106,7 +106,7 @@ public final class Cascade {
// Cascade to an uninitialized, lazy value only if // Cascade to an uninitialized, lazy value only if
// parent is managed in the PersistenceContext. // parent is managed in the PersistenceContext.
// If parent is a detached entity being merged, // If parent is a detached entity being merged,
// then parent will not be in the PersistencContext // then parent will not be in the PersistenceContext
// (so lazy attributes must not be initialized). // (so lazy attributes must not be initialized).
if ( persistenceContext.getEntry( parent ) == null ) { if ( persistenceContext.getEntry( parent ) == null ) {
// parent was not in the PersistenceContext // parent was not in the PersistenceContext
@ -199,8 +199,8 @@ public final class Cascade {
/** /**
* Cascade an action to the child or children * Cascade an action to the child or children
*/ */
private static void cascadeProperty( private static <T> void cascadeProperty(
final CascadingAction action, final CascadingAction<T> action,
final CascadePoint cascadePoint, final CascadePoint cascadePoint,
final EventSource eventSource, final EventSource eventSource,
List<String> componentPath, List<String> componentPath,
@ -209,7 +209,7 @@ public final class Cascade {
final Type type, final Type type,
final CascadeStyle style, final CascadeStyle style,
final String propertyName, final String propertyName,
final Object anything, final T anything,
final boolean isCascadeDeleteEnabled) throws HibernateException { final boolean isCascadeDeleteEnabled) throws HibernateException {
if ( child != null ) { if ( child != null ) {
@ -265,8 +265,8 @@ public final class Cascade {
isCascadeDeleteEnabled ); isCascadeDeleteEnabled );
} }
private static void cascadeLogicalOneToOneOrphanRemoval( private static <T> void cascadeLogicalOneToOneOrphanRemoval(
final CascadingAction action, final CascadingAction<T> action,
final EventSource eventSource, final EventSource eventSource,
final List<String> componentPath, final List<String> componentPath,
final Object parent, final Object parent,
@ -355,7 +355,7 @@ public final class Cascade {
} }
else { else {
// Else, we must delete after the updates. // Else, we must delete after the updates.
eventSource.delete( entityName, loadedValue, isCascadeDeleteEnabled, new HashSet<>() ); eventSource.delete( entityName, loadedValue, isCascadeDeleteEnabled, DeleteContext.create() );
} }
} }
} }
@ -380,15 +380,15 @@ public final class Cascade {
return associationType.getForeignKeyDirection().cascadeNow( cascadePoint ); return associationType.getForeignKeyDirection().cascadeNow( cascadePoint );
} }
private static void cascadeComponent( private static <T> void cascadeComponent(
final CascadingAction action, final CascadingAction<T> action,
final CascadePoint cascadePoint, final CascadePoint cascadePoint,
final EventSource eventSource, final EventSource eventSource,
final List<String> componentPath, final List<String> componentPath,
final Object parent, final Object parent,
final Object child, final Object child,
final CompositeType componentType, final CompositeType componentType,
final Object anything) { final T anything) {
Object[] children = null; Object[] children = null;
final Type[] types = componentType.getSubtypes(); final Type[] types = componentType.getSubtypes();
@ -418,8 +418,8 @@ public final class Cascade {
} }
} }
private static void cascadeAssociation( private static <T> void cascadeAssociation(
final CascadingAction action, final CascadingAction<T> action,
final CascadePoint cascadePoint, final CascadePoint cascadePoint,
final EventSource eventSource, final EventSource eventSource,
final List<String> componentPath, final List<String> componentPath,
@ -427,7 +427,7 @@ public final class Cascade {
final Object child, final Object child,
final Type type, final Type type,
final CascadeStyle style, final CascadeStyle style,
final Object anything, final T anything,
final boolean isCascadeDeleteEnabled) { final boolean isCascadeDeleteEnabled) {
if ( type.isEntityType() || type.isAnyType() ) { if ( type.isEntityType() || type.isAnyType() ) {
cascadeToOne( action, eventSource, parent, child, type, style, anything, isCascadeDeleteEnabled ); cascadeToOne( action, eventSource, parent, child, type, style, anything, isCascadeDeleteEnabled );
@ -450,15 +450,15 @@ public final class Cascade {
/** /**
* Cascade an action to a collection * Cascade an action to a collection
*/ */
private static void cascadeCollection( private static <T> void cascadeCollection(
final CascadingAction action, final CascadingAction<T> action,
final CascadePoint cascadePoint, final CascadePoint cascadePoint,
final EventSource eventSource, final EventSource eventSource,
final List<String> componentPath, final List<String> componentPath,
final Object parent, final Object parent,
final Object child, final Object child,
final CascadeStyle style, final CascadeStyle style,
final Object anything, final T anything,
final CollectionType type) { final CollectionType type) {
final CollectionPersister persister = eventSource.getFactory() final CollectionPersister persister = eventSource.getFactory()
.getRuntimeMetamodels() .getRuntimeMetamodels()
@ -492,14 +492,14 @@ public final class Cascade {
/** /**
* Cascade an action to a to-one association or any type * Cascade an action to a to-one association or any type
*/ */
private static void cascadeToOne( private static <T> void cascadeToOne(
final CascadingAction action, final CascadingAction<T> action,
final EventSource eventSource, final EventSource eventSource,
final Object parent, final Object parent,
final Object child, final Object child,
final Type type, final Type type,
final CascadeStyle style, final CascadeStyle style,
final Object anything, final T anything,
final boolean isCascadeDeleteEnabled) { final boolean isCascadeDeleteEnabled) {
final String entityName = type.isEntityType() final String entityName = type.isEntityType()
? ( (EntityType) type ).getAssociatedEntityName() ? ( (EntityType) type ).getAssociatedEntityName()
@ -520,8 +520,8 @@ public final class Cascade {
/** /**
* Cascade to the collection elements * Cascade to the collection elements
*/ */
private static void cascadeCollectionElements( private static <T> void cascadeCollectionElements(
final CascadingAction action, final CascadingAction<T> action,
final CascadePoint cascadePoint, final CascadePoint cascadePoint,
final EventSource eventSource, final EventSource eventSource,
final List<String> componentPath, final List<String> componentPath,
@ -530,9 +530,10 @@ public final class Cascade {
final CollectionType collectionType, final CollectionType collectionType,
final CascadeStyle style, final CascadeStyle style,
final Type elemType, final Type elemType,
final Object anything, final T anything,
final boolean isCascadeDeleteEnabled) throws HibernateException { final boolean isCascadeDeleteEnabled) throws HibernateException {
final boolean reallyDoCascade = style.reallyDoCascade( action ) && child != CollectionType.UNFETCHED_COLLECTION; final boolean reallyDoCascade = style.reallyDoCascade( action )
&& child != CollectionType.UNFETCHED_COLLECTION;
if ( reallyDoCascade ) { if ( reallyDoCascade ) {
final boolean traceEnabled = LOG.isTraceEnabled(); final boolean traceEnabled = LOG.isTraceEnabled();
@ -605,7 +606,7 @@ public final class Cascade {
for ( Object orphan : orphans ) { for ( Object orphan : orphans ) {
if ( orphan != null ) { if ( orphan != null ) {
LOG.tracev( "Deleting orphaned entity instance: {0}", entityName ); LOG.tracev( "Deleting orphaned entity instance: {0}", entityName );
eventSource.delete( entityName, orphan, false, new HashSet<>() ); eventSource.delete( entityName, orphan, false, DeleteContext.create() );
} }
} }
} }

View File

@ -20,7 +20,7 @@ import org.hibernate.type.Type;
* @author Gavin King * @author Gavin King
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface CascadingAction { public interface CascadingAction<T> {
/** /**
* Cascade the action to the child object. * Cascade the action to the child object.
@ -36,7 +36,7 @@ public interface CascadingAction {
EventSource session, EventSource session,
Object child, Object child,
String entityName, String entityName,
Object anything, T anything,
boolean isCascadeDeleteEnabled) throws HibernateException; boolean isCascadeDeleteEnabled) throws HibernateException;
/** /**

View File

@ -7,8 +7,6 @@
package org.hibernate.engine.spi; package org.hibernate.engine.spi;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.LockMode; import org.hibernate.LockMode;
@ -17,8 +15,11 @@ import org.hibernate.ReplicationMode;
import org.hibernate.TransientPropertyValueException; import org.hibernate.TransientPropertyValueException;
import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.internal.ForeignKeys; import org.hibernate.engine.internal.ForeignKeys;
import org.hibernate.event.spi.DeleteContext;
import org.hibernate.event.spi.MergeContext; import org.hibernate.event.spi.MergeContext;
import org.hibernate.event.spi.EventSource; import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.PersistContext;
import org.hibernate.event.spi.RefreshContext;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
@ -46,16 +47,16 @@ public class CascadingActions {
/** /**
* @see org.hibernate.Session#delete(Object) * @see org.hibernate.Session#delete(Object)
*/ */
public static final CascadingAction DELETE = new BaseCascadingAction() { public static final CascadingAction<DeleteContext> DELETE = new BaseCascadingAction<>() {
@Override @Override
public void cascade( public void cascade(
EventSource session, EventSource session,
Object child, Object child,
String entityName, String entityName,
Object anything, DeleteContext context,
boolean isCascadeDeleteEnabled) { boolean isCascadeDeleteEnabled) {
LOG.tracev( "Cascading to delete: {0}", entityName ); LOG.tracev( "Cascading to delete: {0}", entityName );
session.delete( entityName, child, isCascadeDeleteEnabled, (Set<?>) anything ); session.delete( entityName, child, isCascadeDeleteEnabled, context );
} }
@Override @Override
@ -82,19 +83,18 @@ public class CascadingActions {
/** /**
* @see org.hibernate.Session#lock(Object, LockMode) * @see org.hibernate.Session#lock(Object, LockMode)
*/ */
public static final CascadingAction LOCK = new BaseCascadingAction() { public static final CascadingAction<LockOptions> LOCK = new BaseCascadingAction<>() {
@Override @Override
public void cascade( public void cascade(
EventSource session, EventSource session,
Object child, Object child,
String entityName, String entityName,
Object anything, LockOptions lockOptions,
boolean isCascadeDeleteEnabled) { boolean isCascadeDeleteEnabled) {
LOG.tracev( "Cascading to lock: {0}", entityName ); LOG.tracev( "Cascading to lock: {0}", entityName );
LockMode lockMode = LockMode.NONE; LockMode lockMode = LockMode.NONE;
LockOptions lr = new LockOptions(); LockOptions lr = new LockOptions();
if ( anything instanceof LockOptions ) { if ( lockOptions != null ) {
LockOptions lockOptions = (LockOptions) anything;
lr.setTimeOut( lockOptions.getTimeOut() ); lr.setTimeOut( lockOptions.getTimeOut() );
lr.setScope( lockOptions.getScope() ); lr.setScope( lockOptions.getScope() );
lr.setFollowOnLocking( lockOptions.getFollowOnLocking() ); lr.setFollowOnLocking( lockOptions.getFollowOnLocking() );
@ -130,17 +130,17 @@ public class CascadingActions {
/** /**
* @see org.hibernate.Session#refresh(Object) * @see org.hibernate.Session#refresh(Object)
*/ */
public static final CascadingAction REFRESH = new BaseCascadingAction() { public static final CascadingAction<RefreshContext> REFRESH = new BaseCascadingAction<>() {
@Override @Override
public void cascade( public void cascade(
EventSource session, EventSource session,
Object child, Object child,
String entityName, String entityName,
Object anything, RefreshContext context,
boolean isCascadeDeleteEnabled) boolean isCascadeDeleteEnabled)
throws HibernateException { throws HibernateException {
LOG.tracev( "Cascading to refresh: {0}", entityName ); LOG.tracev( "Cascading to refresh: {0}", entityName );
session.refresh( entityName, child, (Map<?,?>) anything ); session.refresh( entityName, child, context );
} }
@Override @Override
@ -166,13 +166,13 @@ public class CascadingActions {
/** /**
* @see org.hibernate.Session#evict(Object) * @see org.hibernate.Session#evict(Object)
*/ */
public static final CascadingAction EVICT = new BaseCascadingAction() { public static final CascadingAction<Void> EVICT = new BaseCascadingAction<>() {
@Override @Override
public void cascade( public void cascade(
EventSource session, EventSource session,
Object child, Object child,
String entityName, String entityName,
Object anything, Void nothing,
boolean isCascadeDeleteEnabled) boolean isCascadeDeleteEnabled)
throws HibernateException { throws HibernateException {
LOG.tracev( "Cascading to evict: {0}", entityName ); LOG.tracev( "Cascading to evict: {0}", entityName );
@ -207,13 +207,13 @@ public class CascadingActions {
/** /**
* @see org.hibernate.Session#saveOrUpdate(Object) * @see org.hibernate.Session#saveOrUpdate(Object)
*/ */
public static final CascadingAction SAVE_UPDATE = new BaseCascadingAction() { public static final CascadingAction<PersistContext> SAVE_UPDATE = new BaseCascadingAction<>() {
@Override @Override
public void cascade( public void cascade(
EventSource session, EventSource session,
Object child, Object child,
String entityName, String entityName,
Object anything, PersistContext nothing,
boolean isCascadeDeleteEnabled) boolean isCascadeDeleteEnabled)
throws HibernateException { throws HibernateException {
LOG.tracev( "Cascading to save or update: {0}", entityName ); LOG.tracev( "Cascading to save or update: {0}", entityName );
@ -249,17 +249,17 @@ public class CascadingActions {
/** /**
* @see org.hibernate.Session#merge(Object) * @see org.hibernate.Session#merge(Object)
*/ */
public static final CascadingAction MERGE = new BaseCascadingAction() { public static final CascadingAction<MergeContext> MERGE = new BaseCascadingAction<>() {
@Override @Override
public void cascade( public void cascade(
EventSource session, EventSource session,
Object child, Object child,
String entityName, String entityName,
Object anything, MergeContext context,
boolean isCascadeDeleteEnabled) boolean isCascadeDeleteEnabled)
throws HibernateException { throws HibernateException {
LOG.tracev( "Cascading to merge: {0}", entityName ); LOG.tracev( "Cascading to merge: {0}", entityName );
session.merge( entityName, child, (MergeContext) anything ); session.merge( entityName, child, context );
} }
@Override @Override
@ -286,17 +286,17 @@ public class CascadingActions {
/** /**
* @see org.hibernate.Session#persist(Object) * @see org.hibernate.Session#persist(Object)
*/ */
public static final CascadingAction PERSIST = new BaseCascadingAction() { public static final CascadingAction<PersistContext> PERSIST = new BaseCascadingAction<>() {
@Override @Override
public void cascade( public void cascade(
EventSource session, EventSource session,
Object child, Object child,
String entityName, String entityName,
Object anything, PersistContext context,
boolean isCascadeDeleteEnabled) boolean isCascadeDeleteEnabled)
throws HibernateException { throws HibernateException {
LOG.tracev( "Cascading to persist: {0}", entityName ); LOG.tracev( "Cascading to persist: {0}", entityName );
session.persist( entityName, child, (Map<?,?>) anything ); session.persist( entityName, child, context );
} }
@Override @Override
@ -329,17 +329,17 @@ public class CascadingActions {
* *
* @see org.hibernate.Session#persist(Object) * @see org.hibernate.Session#persist(Object)
*/ */
public static final CascadingAction PERSIST_ON_FLUSH = new BaseCascadingAction() { public static final CascadingAction<PersistContext> PERSIST_ON_FLUSH = new BaseCascadingAction<>() {
@Override @Override
public void cascade( public void cascade(
EventSource session, EventSource session,
Object child, Object child,
String entityName, String entityName,
Object anything, PersistContext anything,
boolean isCascadeDeleteEnabled) boolean isCascadeDeleteEnabled)
throws HibernateException { throws HibernateException {
LOG.tracev( "Cascading to persist on flush: {0}", entityName ); LOG.tracev( "Cascading to persist on flush: {0}", entityName );
session.persistOnFlush( entityName, child, (Map<?,?>) anything ); session.persistOnFlush( entityName, child, anything );
} }
@Override @Override
@ -373,8 +373,9 @@ public class CascadingActions {
if ( child != null if ( child != null
&& !isInManagedState( child, session ) && !isInManagedState( child, session )
&& !(child instanceof HibernateProxy) ) { //a proxy cannot be transient and it breaks ForeignKeys.isTransient && !(child instanceof HibernateProxy) ) { //a proxy cannot be transient and it breaks ForeignKeys.isTransient
final String childEntityName = ((EntityType) propertyType).getAssociatedEntityName(session.getFactory()); final String childEntityName =
if (ForeignKeys.isTransient(childEntityName, child, null, session)) { ((EntityType) propertyType).getAssociatedEntityName( session.getFactory() );
if ( ForeignKeys.isTransient(childEntityName, child, null, session) ) {
String parentEntityName = persister.getEntityName(); String parentEntityName = persister.getEntityName();
String propertyName = persister.getPropertyNames()[propertyIndex]; String propertyName = persister.getPropertyNames()[propertyIndex];
throw new TransientPropertyValueException( throw new TransientPropertyValueException(
@ -412,17 +413,17 @@ public class CascadingActions {
/** /**
* @see org.hibernate.Session#replicate * @see org.hibernate.Session#replicate
*/ */
public static final CascadingAction REPLICATE = new BaseCascadingAction() { public static final CascadingAction<ReplicationMode> REPLICATE = new BaseCascadingAction<>() {
@Override @Override
public void cascade( public void cascade(
EventSource session, EventSource session,
Object child, Object child,
String entityName, String entityName,
Object anything, ReplicationMode anything,
boolean isCascadeDeleteEnabled) boolean isCascadeDeleteEnabled)
throws HibernateException { throws HibernateException {
LOG.tracev( "Cascading to replicate: {0}", entityName ); LOG.tracev( "Cascading to replicate: {0}", entityName );
session.replicate( entityName, child, (ReplicationMode) anything ); session.replicate( entityName, child, anything );
} }
@Override @Override
@ -445,7 +446,7 @@ public class CascadingActions {
} }
}; };
public abstract static class BaseCascadingAction implements CascadingAction { public abstract static class BaseCascadingAction<T> implements CascadingAction<T> {
@Override @Override
public boolean requiresNoCascadeChecking() { public boolean requiresNoCascadeChecking() {
return false; return false;

View File

@ -37,7 +37,10 @@ import org.hibernate.engine.jdbc.LobCreator;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess; import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.spi.JdbcCoordinator; import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.event.spi.DeleteContext;
import org.hibernate.event.spi.MergeContext; import org.hibernate.event.spi.MergeContext;
import org.hibernate.event.spi.PersistContext;
import org.hibernate.event.spi.RefreshContext;
import org.hibernate.graph.spi.RootGraphImplementor; import org.hibernate.graph.spi.RootGraphImplementor;
import org.hibernate.jdbc.ReturningWork; import org.hibernate.jdbc.ReturningWork;
import org.hibernate.jdbc.Work; import org.hibernate.jdbc.Work;
@ -1102,22 +1105,22 @@ public class SessionDelegatorBaseImpl implements SessionImplementor {
} }
@Override @Override
public void persist(String entityName, Object object, Map createdAlready) throws HibernateException { public void persist(String entityName, Object object, PersistContext createdAlready) throws HibernateException {
delegate.persist( entityName, object, createdAlready ); delegate.persist( entityName, object, createdAlready );
} }
@Override @Override
public void persistOnFlush(String entityName, Object object, Map copiedAlready) { public void persistOnFlush(String entityName, Object object, PersistContext copiedAlready) {
delegate.persistOnFlush( entityName, object, copiedAlready ); delegate.persistOnFlush( entityName, object, copiedAlready );
} }
@Override @Override
public void refresh(String entityName, Object object, Map refreshedAlready) throws HibernateException { public void refresh(String entityName, Object object, RefreshContext refreshedAlready) throws HibernateException {
delegate.refresh( entityName, object, refreshedAlready ); delegate.refresh( entityName, object, refreshedAlready );
} }
@Override @Override
public void delete(String entityName, Object child, boolean isCascadeDeleteEnabled, Set transientEntities) { public void delete(String entityName, Object child, boolean isCascadeDeleteEnabled, DeleteContext transientEntities) {
delegate.delete( entityName, child, isCascadeDeleteEnabled, transientEntities ); delegate.delete( entityName, child, isCascadeDeleteEnabled, transientEntities );
} }

View File

@ -11,7 +11,10 @@ import java.util.Set;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.event.spi.DeleteContext;
import org.hibernate.event.spi.MergeContext; import org.hibernate.event.spi.MergeContext;
import org.hibernate.event.spi.PersistContext;
import org.hibernate.event.spi.RefreshContext;
import org.hibernate.graph.spi.RootGraphImplementor; import org.hibernate.graph.spi.RootGraphImplementor;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.resource.transaction.spi.TransactionCoordinator; import org.hibernate.resource.transaction.spi.TransactionCoordinator;
@ -84,25 +87,25 @@ public interface SessionImplementor extends Session, SharedSessionContractImplem
* @deprecated OperationalContext should cover this overload I believe * @deprecated OperationalContext should cover this overload I believe
*/ */
@Deprecated @Deprecated
void persist(String entityName, Object object, Map createdAlready) throws HibernateException; void persist(String entityName, Object object, PersistContext createdAlready) throws HibernateException;
/** /**
* @deprecated OperationalContext should cover this overload I believe * @deprecated OperationalContext should cover this overload I believe
*/ */
@Deprecated @Deprecated
void persistOnFlush(String entityName, Object object, Map copiedAlready); void persistOnFlush(String entityName, Object object, PersistContext copiedAlready);
/** /**
* @deprecated OperationalContext should cover this overload I believe * @deprecated OperationalContext should cover this overload I believe
*/ */
@Deprecated @Deprecated
void refresh(String entityName, Object object, Map refreshedAlready) throws HibernateException; void refresh(String entityName, Object object, RefreshContext refreshedAlready) throws HibernateException;
/** /**
* @deprecated OperationalContext should cover this overload I believe * @deprecated OperationalContext should cover this overload I believe
*/ */
@Deprecated @Deprecated
void delete(String entityName, Object child, boolean isCascadeDeleteEnabled, Set transientEntities); void delete(String entityName, Object child, boolean isCascadeDeleteEnabled, DeleteContext transientEntities);
/** /**
* @deprecated OperationalContext should cover this overload I believe * @deprecated OperationalContext should cover this overload I believe

View File

@ -6,7 +6,6 @@
*/ */
package org.hibernate.event.internal; package org.hibernate.event.internal;
import java.util.IdentityHashMap;
import java.util.Map; import java.util.Map;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
@ -33,6 +32,7 @@ import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.FlushEntityEvent; import org.hibernate.event.spi.FlushEntityEvent;
import org.hibernate.event.spi.FlushEntityEventListener; import org.hibernate.event.spi.FlushEntityEventListener;
import org.hibernate.event.spi.FlushEvent; import org.hibernate.event.spi.FlushEvent;
import org.hibernate.event.spi.PersistContext;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.EntityPrinter; import org.hibernate.internal.util.EntityPrinter;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
@ -135,19 +135,19 @@ public abstract class AbstractFlushingEventListener implements JpaBootstrapSensi
LOG.debug( "Processing flush-time cascades" ); LOG.debug( "Processing flush-time cascades" );
final Object anything = getAnything(); final PersistContext context = getContext();
//safe from concurrent modification because of how concurrentEntries() is implemented on IdentityMap //safe from concurrent modification because of how concurrentEntries() is implemented on IdentityMap
for ( Map.Entry<Object,EntityEntry> me : persistenceContext.reentrantSafeEntityEntries() ) { for ( Map.Entry<Object,EntityEntry> me : persistenceContext.reentrantSafeEntityEntries() ) {
// for ( Map.Entry me : IdentityMap.concurrentEntries( persistenceContext.getEntityEntries() ) ) { // for ( Map.Entry me : IdentityMap.concurrentEntries( persistenceContext.getEntityEntries() ) ) {
EntityEntry entry = me.getValue(); EntityEntry entry = me.getValue();
Status status = entry.getStatus(); Status status = entry.getStatus();
if ( status == Status.MANAGED || status == Status.SAVING || status == Status.READ_ONLY ) { if ( status == Status.MANAGED || status == Status.SAVING || status == Status.READ_ONLY ) {
cascadeOnFlush( session, entry.getPersister(), me.getKey(), anything ); cascadeOnFlush( session, entry.getPersister(), me.getKey(), context );
} }
} }
} }
private void cascadeOnFlush(EventSource session, EntityPersister persister, Object object, Object anything) private void cascadeOnFlush(EventSource session, EntityPersister persister, Object object, PersistContext anything)
throws HibernateException { throws HibernateException {
final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
persistenceContext.incrementCascadeLevel(); persistenceContext.incrementCascadeLevel();
@ -159,11 +159,11 @@ public abstract class AbstractFlushingEventListener implements JpaBootstrapSensi
} }
} }
protected Object getAnything() { protected PersistContext getContext() {
return jpaBootstrap ? new IdentityHashMap<>(10) : null; return jpaBootstrap ? PersistContext.create() : null;
} }
protected CascadingAction getCascadingAction() { protected CascadingAction<PersistContext> getCascadingAction() {
return jpaBootstrap ? CascadingActions.PERSIST_ON_FLUSH : CascadingActions.SAVE_UPDATE; return jpaBootstrap ? CascadingActions.PERSIST_ON_FLUSH : CascadingActions.SAVE_UPDATE;
} }
@ -177,9 +177,7 @@ public abstract class AbstractFlushingEventListener implements JpaBootstrapSensi
// and reset reached, doupdate, etc. // and reset reached, doupdate, etc.
LOG.debug( "Dirty checking collections" ); LOG.debug( "Dirty checking collections" );
persistenceContext.forEachCollectionEntry( (pc,ce) -> { persistenceContext.forEachCollectionEntry( (pc,ce) -> ce.preFlush( pc ), true );
ce.preFlush( pc );
}, true );
} }
/** /**

View File

@ -42,7 +42,7 @@ import org.hibernate.type.TypeHelper;
* *
* @author Steve Ebersole. * @author Steve Ebersole.
*/ */
public abstract class AbstractSaveEventListener public abstract class AbstractSaveEventListener<C>
extends AbstractReassociateEventListener extends AbstractReassociateEventListener
implements CallbackRegistryConsumer { implements CallbackRegistryConsumer {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( AbstractSaveEventListener.class ); private static final CoreMessageLogger LOG = CoreLogging.messageLogger( AbstractSaveEventListener.class );
@ -59,7 +59,7 @@ public abstract class AbstractSaveEventListener
* @param entity The entity to be saved. * @param entity The entity to be saved.
* @param requestedId The id to which to associate the entity. * @param requestedId The id to which to associate the entity.
* @param entityName The name of the entity being saved. * @param entityName The name of the entity being saved.
* @param anything Generally cascade-specific information. * @param context Generally cascade-specific information.
* @param source The session which is the source of this save event. * @param source The session which is the source of this save event.
* *
* @return The id used to save the entity. * @return The id used to save the entity.
@ -68,7 +68,7 @@ public abstract class AbstractSaveEventListener
Object entity, Object entity,
Object requestedId, Object requestedId,
String entityName, String entityName,
Object anything, C context,
EventSource source) { EventSource source) {
callbackRegistry.preCreate( entity ); callbackRegistry.preCreate( entity );
@ -77,7 +77,7 @@ public abstract class AbstractSaveEventListener
requestedId, requestedId,
source.getEntityPersister( entityName, entity ), source.getEntityPersister( entityName, entity ),
false, false,
anything, context,
source, source,
true true
); );
@ -88,7 +88,7 @@ public abstract class AbstractSaveEventListener
* *
* @param entity The entity to be saved * @param entity The entity to be saved
* @param entityName The entity-name for the entity to be saved * @param entityName The entity-name for the entity to be saved
* @param anything Generally cascade-specific information. * @param context Generally cascade-specific information.
* @param source The session which is the source of this save event. * @param source The session which is the source of this save event.
* @param requiresImmediateIdAccess does the event context require * @param requiresImmediateIdAccess does the event context require
* access to the identifier immediately after execution of this method (if * access to the identifier immediately after execution of this method (if
@ -101,7 +101,7 @@ public abstract class AbstractSaveEventListener
protected Object saveWithGeneratedId( protected Object saveWithGeneratedId(
Object entity, Object entity,
String entityName, String entityName,
Object anything, C context,
EventSource source, EventSource source,
boolean requiresImmediateIdAccess) { boolean requiresImmediateIdAccess) {
callbackRegistry.preCreate( entity ); callbackRegistry.preCreate( entity );
@ -119,7 +119,7 @@ public abstract class AbstractSaveEventListener
return source.getIdentifier( entity ); return source.getIdentifier( entity );
} }
else if ( generatedId == IdentifierGeneratorHelper.POST_INSERT_INDICATOR ) { else if ( generatedId == IdentifierGeneratorHelper.POST_INSERT_INDICATOR ) {
return performSave( entity, null, persister, true, anything, source, requiresImmediateIdAccess ); return performSave( entity, null, persister, true, context, source, requiresImmediateIdAccess );
} }
else { else {
// TODO: define toString()s for generators // TODO: define toString()s for generators
@ -131,7 +131,7 @@ public abstract class AbstractSaveEventListener
); );
} }
return performSave( entity, generatedId, persister, false, anything, source, true ); return performSave( entity, generatedId, persister, false, context, source, true );
} }
} }
@ -143,7 +143,7 @@ public abstract class AbstractSaveEventListener
* @param id The id by which to save the entity. * @param id The id by which to save the entity.
* @param persister The entity's persister instance. * @param persister The entity's persister instance.
* @param useIdentityColumn Is an identity column being used? * @param useIdentityColumn Is an identity column being used?
* @param anything Generally cascade-specific information. * @param context Generally cascade-specific information.
* @param source The session from which the event originated. * @param source The session from which the event originated.
* @param requiresImmediateIdAccess does the event context require * @param requiresImmediateIdAccess does the event context require
* access to the identifier immediately after execution of this method (if * access to the identifier immediately after execution of this method (if
@ -158,7 +158,7 @@ public abstract class AbstractSaveEventListener
Object id, Object id,
EntityPersister persister, EntityPersister persister,
boolean useIdentityColumn, boolean useIdentityColumn,
Object anything, C context,
EventSource source, EventSource source,
boolean requiresImmediateIdAccess) { boolean requiresImmediateIdAccess) {
@ -194,7 +194,7 @@ public abstract class AbstractSaveEventListener
key, key,
persister, persister,
useIdentityColumn, useIdentityColumn,
anything, context,
source, source,
requiresImmediateIdAccess requiresImmediateIdAccess
); );
@ -221,7 +221,7 @@ public abstract class AbstractSaveEventListener
* @param key The id to be used for saving the entity (or null, in the case of identity columns) * @param key The id to be used for saving the entity (or null, in the case of identity columns)
* @param persister The entity's persister instance. * @param persister The entity's persister instance.
* @param useIdentityColumn Should an identity column be used for id generation? * @param useIdentityColumn Should an identity column be used for id generation?
* @param anything Generally cascade-specific information. * @param context Generally cascade-specific information.
* @param source The session which is the source of the current event. * @param source The session which is the source of the current event.
* @param requiresImmediateIdAccess Is access to the identifier required immediately * @param requiresImmediateIdAccess Is access to the identifier required immediately
* after the completion of the save? persist(), for example, does not require this... * after the completion of the save? persist(), for example, does not require this...
@ -234,7 +234,7 @@ public abstract class AbstractSaveEventListener
EntityKey key, EntityKey key,
EntityPersister persister, EntityPersister persister,
boolean useIdentityColumn, boolean useIdentityColumn,
Object anything, C context,
EventSource source, EventSource source,
boolean requiresImmediateIdAccess) { boolean requiresImmediateIdAccess) {
@ -260,9 +260,9 @@ public abstract class AbstractSaveEventListener
false false
); );
cascadeBeforeSave( source, persister, entity, anything ); cascadeBeforeSave( source, persister, entity, context );
Object[] values = persister.getPropertyValuesToInsert( entity, getMergeMap( anything ), source ); Object[] values = persister.getPropertyValuesToInsert( entity, getMergeMap( context ), source );
Type[] types = persister.getPropertyTypes(); Type[] types = persister.getPropertyTypes();
boolean substitute = substituteValuesIfNecessary( entity, id, values, persister, source ); boolean substitute = substituteValuesIfNecessary( entity, id, values, persister, source );
@ -295,7 +295,7 @@ public abstract class AbstractSaveEventListener
// postpone initializing id in case the insert has non-nullable transient dependencies // postpone initializing id in case the insert has non-nullable transient dependencies
// that are not resolved until cascadeAfterSave() is executed // that are not resolved until cascadeAfterSave() is executed
cascadeAfterSave( source, persister, entity, anything ); cascadeAfterSave( source, persister, entity, context );
if ( useIdentityColumn && insert.isEarlyInsert() ) { if ( useIdentityColumn && insert.isEarlyInsert() ) {
if ( !(insert instanceof EntityIdentityInsertAction) ) { if ( !(insert instanceof EntityIdentityInsertAction) ) {
throw new IllegalStateException( throw new IllegalStateException(
@ -355,7 +355,7 @@ public abstract class AbstractSaveEventListener
} }
} }
protected Map<Object,Object> getMergeMap(Object anything) { protected Map<Object,Object> getMergeMap(C anything) {
return null; return null;
} }
@ -427,13 +427,13 @@ public abstract class AbstractSaveEventListener
* @param source The session from which the save event originated. * @param source The session from which the save event originated.
* @param persister The entity's persister instance. * @param persister The entity's persister instance.
* @param entity The entity to be saved. * @param entity The entity to be saved.
* @param anything Generally cascade-specific data * @param context Generally cascade-specific data
*/ */
protected void cascadeBeforeSave( protected void cascadeBeforeSave(
EventSource source, EventSource source,
EntityPersister persister, EntityPersister persister,
Object entity, Object entity,
Object anything) { C context) {
// cascade-save to many-to-one BEFORE the parent is saved // cascade-save to many-to-one BEFORE the parent is saved
final PersistenceContext persistenceContext = source.getPersistenceContextInternal(); final PersistenceContext persistenceContext = source.getPersistenceContextInternal();
@ -445,7 +445,7 @@ public abstract class AbstractSaveEventListener
source, source,
persister, persister,
entity, entity,
anything context
); );
} }
finally { finally {
@ -459,13 +459,13 @@ public abstract class AbstractSaveEventListener
* @param source The session from which the event originated. * @param source The session from which the event originated.
* @param persister The entity's persister instance. * @param persister The entity's persister instance.
* @param entity The entity being saved. * @param entity The entity being saved.
* @param anything Generally cascade-specific data * @param context Generally cascade-specific data
*/ */
protected void cascadeAfterSave( protected void cascadeAfterSave(
EventSource source, EventSource source,
EntityPersister persister, EntityPersister persister,
Object entity, Object entity,
Object anything) { C context) {
final PersistenceContext persistenceContext = source.getPersistenceContextInternal(); final PersistenceContext persistenceContext = source.getPersistenceContextInternal();
// cascade-save to collections AFTER the collection owner was saved // cascade-save to collections AFTER the collection owner was saved
@ -477,7 +477,7 @@ public abstract class AbstractSaveEventListener
source, source,
persister, persister,
entity, entity,
anything context
); );
} }
finally { finally {
@ -485,6 +485,6 @@ public abstract class AbstractSaveEventListener
} }
} }
protected abstract CascadingAction getCascadeAction(); protected abstract CascadingAction<C> getCascadeAction();
} }

View File

@ -6,8 +6,6 @@
*/ */
package org.hibernate.event.internal; package org.hibernate.event.internal;
import java.util.Set;
import org.hibernate.CacheMode; import org.hibernate.CacheMode;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.LockMode; import org.hibernate.LockMode;
@ -26,12 +24,12 @@ import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.Status; import org.hibernate.engine.spi.Status;
import org.hibernate.event.service.spi.JpaBootstrapSensitive; import org.hibernate.event.service.spi.JpaBootstrapSensitive;
import org.hibernate.event.spi.DeleteContext;
import org.hibernate.event.spi.DeleteEvent; import org.hibernate.event.spi.DeleteEvent;
import org.hibernate.event.spi.DeleteEventListener; import org.hibernate.event.spi.DeleteEventListener;
import org.hibernate.event.spi.EventSource; import org.hibernate.event.spi.EventSource;
import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger; 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.CallbackRegistry;
import org.hibernate.jpa.event.spi.CallbackRegistryConsumer; import org.hibernate.jpa.event.spi.CallbackRegistryConsumer;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
@ -68,7 +66,7 @@ public class DefaultDeleteEventListener implements DeleteEventListener, Callback
* *
*/ */
public void onDelete(DeleteEvent event) throws HibernateException { public void onDelete(DeleteEvent event) throws HibernateException {
onDelete( event, new IdentitySet<>() ); onDelete( event, DeleteContext.create() );
} }
/** /**
@ -78,7 +76,7 @@ public class DefaultDeleteEventListener implements DeleteEventListener, Callback
* @param transientEntities The cache of entities already deleted * @param transientEntities The cache of entities already deleted
* *
*/ */
public void onDelete(DeleteEvent event, Set transientEntities) throws HibernateException { public void onDelete(DeleteEvent event, DeleteContext transientEntities) throws HibernateException {
final EventSource source = event.getSession(); final EventSource source = event.getSession();
@ -208,13 +206,12 @@ public class DefaultDeleteEventListener implements DeleteEventListener, Callback
Object entity, Object entity,
boolean cascadeDeleteEnabled, boolean cascadeDeleteEnabled,
EntityPersister persister, EntityPersister persister,
Set transientEntities) { DeleteContext transientEntities) {
LOG.handlingTransientEntity(); LOG.handlingTransientEntity();
if ( transientEntities.contains( entity ) ) { if ( !transientEntities.add( entity ) ) {
LOG.trace( "Already handled transient entity; skipping" ); LOG.trace( "Already handled transient entity; skipping" );
return; return;
} }
transientEntities.add( entity );
cascadeBeforeDelete( session, persister, entity, null, transientEntities ); cascadeBeforeDelete( session, persister, entity, null, transientEntities );
cascadeAfterDelete( session, persister, entity, transientEntities ); cascadeAfterDelete( session, persister, entity, transientEntities );
} }
@ -238,7 +235,7 @@ public class DefaultDeleteEventListener implements DeleteEventListener, Callback
final boolean isCascadeDeleteEnabled, final boolean isCascadeDeleteEnabled,
final boolean isOrphanRemovalBeforeUpdates, final boolean isOrphanRemovalBeforeUpdates,
final EntityPersister persister, final EntityPersister persister,
final Set transientEntities) { final DeleteContext transientEntities) {
if ( LOG.isTraceEnabled() ) { if ( LOG.isTraceEnabled() ) {
LOG.tracev( LOG.tracev(
@ -342,7 +339,7 @@ public class DefaultDeleteEventListener implements DeleteEventListener, Callback
EntityPersister persister, EntityPersister persister,
Object entity, Object entity,
EntityEntry entityEntry, EntityEntry entityEntry,
Set transientEntities) throws HibernateException { DeleteContext transientEntities) throws HibernateException {
CacheMode cacheMode = session.getCacheMode(); CacheMode cacheMode = session.getCacheMode();
session.setCacheMode( CacheMode.GET ); session.setCacheMode( CacheMode.GET );
@ -369,7 +366,7 @@ public class DefaultDeleteEventListener implements DeleteEventListener, Callback
EventSource session, EventSource session,
EntityPersister persister, EntityPersister persister,
Object entity, Object entity,
Set transientEntities) throws HibernateException { DeleteContext transientEntities) throws HibernateException {
CacheMode cacheMode = session.getCacheMode(); CacheMode cacheMode = session.getCacheMode();
session.setCacheMode( CacheMode.GET ); session.setCacheMode( CacheMode.GET );

View File

@ -48,12 +48,14 @@ import org.hibernate.type.TypeHelper;
* *
* @author Gavin King * @author Gavin King
*/ */
public class DefaultMergeEventListener extends AbstractSaveEventListener implements MergeEventListener { public class DefaultMergeEventListener
extends AbstractSaveEventListener<MergeContext>
implements MergeEventListener {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( DefaultMergeEventListener.class ); private static final CoreMessageLogger LOG = CoreLogging.messageLogger( DefaultMergeEventListener.class );
@Override @Override
protected Map<Object,Object> getMergeMap(Object anything) { protected Map<Object,Object> getMergeMap(MergeContext context) {
return ( (MergeContext) anything ).invertMap(); return context.invertMap();
} }
/** /**
@ -126,14 +128,14 @@ public class DefaultMergeEventListener extends AbstractSaveEventListener impleme
entity = original; entity = original;
} }
if ( ((MergeContext) copiedAlready).containsKey( entity ) && ((MergeContext) copiedAlready).isOperatedOn( entity ) ) { if ( copiedAlready.containsKey( entity ) && copiedAlready.isOperatedOn( entity ) ) {
LOG.trace( "Already in merge process" ); LOG.trace( "Already in merge process" );
event.setResult( entity ); event.setResult( entity );
} }
else { else {
if ( ((MergeContext) copiedAlready).containsKey( entity ) ) { if ( copiedAlready.containsKey( entity ) ) {
LOG.trace( "Already in copyCache; setting in merge process" ); LOG.trace( "Already in copyCache; setting in merge process" );
((MergeContext) copiedAlready).setOperatedOn( entity, true ); copiedAlready.setOperatedOn( entity, true );
} }
event.setEntity( entity ); event.setEntity( entity );
EntityState entityState = null; EntityState entityState = null;
@ -166,13 +168,13 @@ public class DefaultMergeEventListener extends AbstractSaveEventListener impleme
switch ( entityState ) { switch ( entityState ) {
case DETACHED: case DETACHED:
entityIsDetached( event, (MergeContext) copiedAlready); entityIsDetached( event, copiedAlready);
break; break;
case TRANSIENT: case TRANSIENT:
entityIsTransient( event, (MergeContext) copiedAlready); entityIsTransient( event, copiedAlready);
break; break;
case PERSISTENT: case PERSISTENT:
entityIsPersistent( event, (MergeContext) copiedAlready); entityIsPersistent( event, copiedAlready);
break; break;
default: //DELETED default: //DELETED
throw new ObjectDeletedException( throw new ObjectDeletedException(
@ -530,7 +532,7 @@ public class DefaultMergeEventListener extends AbstractSaveEventListener impleme
@Override @Override
protected CascadingAction getCascadeAction() { protected CascadingAction<MergeContext> getCascadeAction() {
return CascadingActions.MERGE; return CascadingActions.MERGE;
} }
@ -538,7 +540,7 @@ public class DefaultMergeEventListener extends AbstractSaveEventListener impleme
* Cascade behavior is redefined by this subclass, disable superclass behavior * Cascade behavior is redefined by this subclass, disable superclass behavior
*/ */
@Override @Override
protected void cascadeAfterSave(EventSource source, EntityPersister persister, Object entity, Object anything) protected void cascadeAfterSave(EventSource source, EntityPersister persister, Object entity, MergeContext anything)
throws HibernateException { throws HibernateException {
} }
@ -546,7 +548,7 @@ public class DefaultMergeEventListener extends AbstractSaveEventListener impleme
* Cascade behavior is redefined by this subclass, disable superclass behavior * Cascade behavior is redefined by this subclass, disable superclass behavior
*/ */
@Override @Override
protected void cascadeBeforeSave(EventSource source, EntityPersister persister, Object entity, Object anything) protected void cascadeBeforeSave(EventSource source, EntityPersister persister, Object entity, MergeContext anything)
throws HibernateException { throws HibernateException {
} }
} }

View File

@ -6,9 +6,6 @@
*/ */
package org.hibernate.event.internal; package org.hibernate.event.internal;
import java.util.IdentityHashMap;
import java.util.Map;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.ObjectDeletedException; import org.hibernate.ObjectDeletedException;
import org.hibernate.PersistentObjectException; import org.hibernate.PersistentObjectException;
@ -18,6 +15,7 @@ import org.hibernate.engine.spi.EntityEntry;
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.spi.EventSource; import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.PersistContext;
import org.hibernate.event.spi.PersistEvent; import org.hibernate.event.spi.PersistEvent;
import org.hibernate.event.spi.PersistEventListener; import org.hibernate.event.spi.PersistEventListener;
import org.hibernate.id.ForeignGenerator; import org.hibernate.id.ForeignGenerator;
@ -36,12 +34,12 @@ import org.hibernate.proxy.LazyInitializer;
* @author Gavin King * @author Gavin King
*/ */
public class DefaultPersistEventListener public class DefaultPersistEventListener
extends AbstractSaveEventListener extends AbstractSaveEventListener<PersistContext>
implements PersistEventListener, CallbackRegistryConsumer { implements PersistEventListener, CallbackRegistryConsumer {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( DefaultPersistEventListener.class ); private static final CoreMessageLogger LOG = CoreLogging.messageLogger( DefaultPersistEventListener.class );
@Override @Override
protected CascadingAction getCascadeAction() { protected CascadingAction<PersistContext> getCascadeAction() {
return CascadingActions.PERSIST; return CascadingActions.PERSIST;
} }
@ -52,7 +50,7 @@ public class DefaultPersistEventListener
* *
*/ */
public void onPersist(PersistEvent event) throws HibernateException { public void onPersist(PersistEvent event) throws HibernateException {
onPersist( event, new IdentityHashMap<>( 10 ) ); onPersist( event, PersistContext.create() );
} }
/** /**
@ -61,7 +59,7 @@ public class DefaultPersistEventListener
* @param event The create event to be handled. * @param event The create event to be handled.
* *
*/ */
public void onPersist(PersistEvent event, Map createCache) throws HibernateException { public void onPersist(PersistEvent event, PersistContext createCache) throws HibernateException {
final SessionImplementor source = event.getSession(); final SessionImplementor source = event.getSession();
final Object object = event.getObject(); final Object object = event.getObject();
@ -149,7 +147,7 @@ public class DefaultPersistEventListener
} }
protected void entityIsPersistent(PersistEvent event, Map createCache) { protected void entityIsPersistent(PersistEvent event, PersistContext createCache) {
LOG.trace( "Ignoring persistent instance" ); LOG.trace( "Ignoring persistent instance" );
final EventSource source = event.getSession(); final EventSource source = event.getSession();
@ -158,13 +156,13 @@ public class DefaultPersistEventListener
final Object entity = source.getPersistenceContextInternal().unproxy( event.getObject() ); final Object entity = source.getPersistenceContextInternal().unproxy( event.getObject() );
final EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity ); final EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity );
if ( createCache.put( entity, entity ) == null ) { if ( createCache.add( entity ) ) {
justCascade( createCache, source, entity, persister ); justCascade( createCache, source, entity, persister );
} }
} }
private void justCascade(Map createCache, EventSource source, Object entity, EntityPersister persister) { private void justCascade(PersistContext createCache, EventSource source, Object entity, EntityPersister persister) {
//TODO: merge into one method! //TODO: merge into one method!
cascadeBeforeSave( source, persister, entity, createCache ); cascadeBeforeSave( source, persister, entity, createCache );
cascadeAfterSave( source, persister, entity, createCache ); cascadeAfterSave( source, persister, entity, createCache );
@ -176,18 +174,18 @@ public class DefaultPersistEventListener
* @param event The save event to be handled. * @param event The save event to be handled.
* @param createCache The copy cache of entity instance to merge/copy instance. * @param createCache The copy cache of entity instance to merge/copy instance.
*/ */
protected void entityIsTransient(PersistEvent event, Map createCache) { protected void entityIsTransient(PersistEvent event, PersistContext createCache) {
LOG.trace( "Saving transient instance" ); LOG.trace( "Saving transient instance" );
final EventSource source = event.getSession(); final EventSource source = event.getSession();
final Object entity = source.getPersistenceContextInternal().unproxy( event.getObject() ); final Object entity = source.getPersistenceContextInternal().unproxy( event.getObject() );
if ( createCache.put( entity, entity ) == null ) { if ( createCache.add( entity ) ) {
saveWithGeneratedId( entity, event.getEntityName(), createCache, source, false ); saveWithGeneratedId( entity, event.getEntityName(), createCache, source, false );
} }
} }
private void entityIsDeleted(PersistEvent event, Map createCache) { private void entityIsDeleted(PersistEvent event, PersistContext createCache) {
final EventSource source = event.getSession(); final EventSource source = event.getSession();
final Object entity = source.getPersistenceContextInternal().unproxy( event.getObject() ); final Object entity = source.getPersistenceContextInternal().unproxy( event.getObject() );
@ -204,7 +202,7 @@ public class DefaultPersistEventListener
); );
} }
if ( createCache.put( entity, entity ) == null ) { if ( createCache.add( entity ) ) {
justCascade( createCache, source, entity, persister ); justCascade( createCache, source, entity, persister );
} }
} }

View File

@ -8,13 +8,14 @@ package org.hibernate.event.internal;
import org.hibernate.engine.spi.CascadingAction; import org.hibernate.engine.spi.CascadingAction;
import org.hibernate.engine.spi.CascadingActions; import org.hibernate.engine.spi.CascadingActions;
import org.hibernate.event.spi.PersistContext;
/** /**
* When persist is used as the cascade action, persistOnFlush should be used * When persist is used as the cascade action, persistOnFlush should be used
* @author Emmanuel Bernard * @author Emmanuel Bernard
*/ */
public class DefaultPersistOnFlushEventListener extends DefaultPersistEventListener { public class DefaultPersistOnFlushEventListener extends DefaultPersistEventListener {
protected CascadingAction getCascadeAction() { protected CascadingAction<PersistContext> getCascadeAction() {
return CascadingActions.PERSIST_ON_FLUSH; return CascadingActions.PERSIST_ON_FLUSH;
} }
} }

View File

@ -6,9 +6,6 @@
*/ */
package org.hibernate.event.internal; package org.hibernate.event.internal;
import java.util.IdentityHashMap;
import java.util.Map;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.LockOptions; import org.hibernate.LockOptions;
@ -26,6 +23,7 @@ import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.event.spi.EventSource; import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.RefreshContext;
import org.hibernate.event.spi.RefreshEvent; import org.hibernate.event.spi.RefreshEvent;
import org.hibernate.event.spi.RefreshEventListener; import org.hibernate.event.spi.RefreshEventListener;
import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreLogging;
@ -49,7 +47,7 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( DefaultRefreshEventListener.class ); private static final CoreMessageLogger LOG = CoreLogging.messageLogger( DefaultRefreshEventListener.class );
public void onRefresh(RefreshEvent event) throws HibernateException { public void onRefresh(RefreshEvent event) throws HibernateException {
onRefresh( event, new IdentityHashMap<>( 10 ) ); onRefresh( event, RefreshContext.create() );
} }
/** /**
@ -57,7 +55,7 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
* *
* @param event The refresh event to be handled. * @param event The refresh event to be handled.
*/ */
public void onRefresh(RefreshEvent event, Map refreshedAlready) { public void onRefresh(RefreshEvent event, RefreshContext refreshedAlready) {
final EventSource source = event.getSession(); final EventSource source = event.getSession();
final PersistenceContext persistenceContext = source.getPersistenceContextInternal(); final PersistenceContext persistenceContext = source.getPersistenceContextInternal();
@ -74,7 +72,7 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
final Object object = persistenceContext.unproxyAndReassociate( event.getObject() ); final Object object = persistenceContext.unproxyAndReassociate( event.getObject() );
if ( refreshedAlready.containsKey( object ) ) { if ( !refreshedAlready.add( object ) ) {
LOG.trace( "Already refreshed" ); LOG.trace( "Already refreshed" );
return; return;
} }
@ -126,7 +124,6 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
} }
// cascade the refresh prior to refreshing this entity // cascade the refresh prior to refreshing this entity
refreshedAlready.put( object, object );
Cascade.cascade( Cascade.cascade(
CascadingActions.REFRESH, CascadingActions.REFRESH,
CascadePoint.BEFORE_REFRESH, CascadePoint.BEFORE_REFRESH,
@ -224,7 +221,7 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
if ( result != null ) { if ( result != null ) {
// apply `postRefreshLockMode`, if needed // apply `postRefreshLockMode`, if needed
if ( postRefreshLockMode != null ) { if ( postRefreshLockMode != null ) {
// if we get here, there was a previous entry and we need to re-set its lock-mode // if we get here, there was a previous entry, and we need to re-set its lock-mode
// - however, the refresh operation actually creates a new entry, so get it // - however, the refresh operation actually creates a new entry, so get it
persistenceContext.getEntry( result ).setLockMode( postRefreshLockMode ); persistenceContext.getEntry( result ).setLockMode( postRefreshLockMode );
} }

View File

@ -34,7 +34,9 @@ import org.hibernate.type.Type;
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class DefaultReplicateEventListener extends AbstractSaveEventListener implements ReplicateEventListener { public class DefaultReplicateEventListener
extends AbstractSaveEventListener<ReplicationMode>
implements ReplicateEventListener {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( DefaultReplicateEventListener.class ); private static final CoreMessageLogger LOG = CoreLogging.messageLogger( DefaultReplicateEventListener.class );
/** /**
@ -88,15 +90,14 @@ public class DefaultReplicateEventListener extends AbstractSaveEventListener imp
); );
} }
/// HHH-2378
final Object realOldVersion = persister.isVersioned() ? oldVersion : null;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final BasicType<Object> versionType = (BasicType<Object>) persister.getVersionType();
final Object realOldVersion = persister.isVersioned() ? oldVersion : null; /// HHH-2378
boolean canReplicate = replicationMode.shouldOverwriteCurrentVersion( boolean canReplicate = replicationMode.shouldOverwriteCurrentVersion(
entity, entity,
realOldVersion, realOldVersion,
persister.getVersion( entity ), persister.getVersion( entity ),
(BasicType<Object>) persister.getVersionType() versionType
); );
// if can replicate, will result in a SQL UPDATE // if can replicate, will result in a SQL UPDATE
@ -215,7 +216,7 @@ public class DefaultReplicateEventListener extends AbstractSaveEventListener imp
} }
@Override @Override
protected CascadingAction getCascadeAction() { protected CascadingAction<ReplicationMode> getCascadeAction() {
return CascadingActions.REPLICATE; return CascadingActions.REPLICATE;
} }
} }

View File

@ -23,6 +23,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
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.spi.EventSource; import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.PersistContext;
import org.hibernate.event.spi.SaveOrUpdateEvent; import org.hibernate.event.spi.SaveOrUpdateEvent;
import org.hibernate.event.spi.SaveOrUpdateEventListener; import org.hibernate.event.spi.SaveOrUpdateEventListener;
import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreLogging;
@ -38,7 +39,9 @@ import org.hibernate.proxy.HibernateProxy;
* @author Steve Ebersole * @author Steve Ebersole
* @author Gavin King * @author Gavin King
*/ */
public class DefaultSaveOrUpdateEventListener extends AbstractSaveEventListener implements SaveOrUpdateEventListener { public class DefaultSaveOrUpdateEventListener
extends AbstractSaveEventListener<PersistContext>
implements SaveOrUpdateEventListener {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( DefaultSaveOrUpdateEventListener.class ); private static final CoreMessageLogger LOG = CoreLogging.messageLogger( DefaultSaveOrUpdateEventListener.class );
/** /**
@ -363,7 +366,7 @@ public class DefaultSaveOrUpdateEventListener extends AbstractSaveEventListener
} }
@Override @Override
protected CascadingAction getCascadeAction() { protected CascadingAction<PersistContext> getCascadeAction() {
return CascadingActions.SAVE_UPDATE; return CascadingActions.SAVE_UPDATE;
} }
} }

View File

@ -0,0 +1,38 @@
/*
* 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.spi;
import java.util.IdentityHashMap;
/**
* A {@link DeleteEvent} represents a {@linkplain org.hibernate.Session#delete(Object) delete operation}
* applied to a single entity. A {@code DeleteContext} is propagated across all cascaded delete operations,
* and keeps track of all the entities we've already visited.
*
* @author Gavin King
*/
public interface DeleteContext {
boolean add(Object entity);
static DeleteContext create() {
// use extension to avoid creating
// a useless wrapper object
class Impl extends IdentityHashMap<Object,Object>
implements DeleteContext {
Impl() {
super(10);
}
@Override
public boolean add(Object entity) {
return put(entity,entity)==null;
}
}
return new Impl();
}
}

View File

@ -24,5 +24,5 @@ public interface DeleteEventListener {
*/ */
void onDelete(DeleteEvent event) throws HibernateException; void onDelete(DeleteEvent event) throws HibernateException;
void onDelete(DeleteEvent event, Set transientEntities) throws HibernateException; void onDelete(DeleteEvent event, DeleteContext transientEntities) throws HibernateException;
} }

View File

@ -6,9 +6,6 @@
*/ */
package org.hibernate.event.spi; package org.hibernate.event.spi;
import java.util.Map;
import java.util.Set;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.engine.spi.ActionQueue; import org.hibernate.engine.spi.ActionQueue;
import org.hibernate.engine.spi.EntityEntry; import org.hibernate.engine.spi.EntityEntry;
@ -43,20 +40,20 @@ public interface EventSource extends SessionImplementor {
/** /**
* Cascade persist an entity instance * Cascade persist an entity instance
*/ */
void persist(String entityName, Object object, Map createdAlready) throws HibernateException; void persist(String entityName, Object object, PersistContext createdAlready) throws HibernateException;
/** /**
* Cascade persist an entity instance during the flush process * Cascade persist an entity instance during the flush process
*/ */
void persistOnFlush(String entityName, Object object, Map copiedAlready); void persistOnFlush(String entityName, Object object, PersistContext copiedAlready);
/** /**
* Cascade refresh an entity instance * Cascade refresh an entity instance
*/ */
void refresh(String entityName, Object object, Map refreshedAlready) throws HibernateException; void refresh(String entityName, Object object, RefreshContext refreshedAlready) throws HibernateException;
/** /**
* Cascade delete an entity instance * Cascade delete an entity instance
*/ */
void delete(String entityName, Object child, boolean isCascadeDeleteEnabled, Set transientEntities); void delete(String entityName, Object child, boolean isCascadeDeleteEnabled, DeleteContext transientEntities);
/** /**
* A specialized type of deletion for orphan removal that must occur prior to queued inserts and updates. * A specialized type of deletion for orphan removal that must occur prior to queued inserts and updates.
*/ */

View File

@ -0,0 +1,38 @@
/*
* 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.spi;
import java.util.IdentityHashMap;
/**
* A {@link PersistEvent} represents a {@linkplain org.hibernate.Session#persist(Object) persist operation}
* applied to a single entity. A {@code PersistContext} is propagated across all cascaded persist operations,
* and keeps track of all the entities we've already visited.
*
* @author Gavin King
*/
public interface PersistContext {
boolean add(Object entity);
static PersistContext create() {
// use extension to avoid creating
// a useless wrapper object
class Impl extends IdentityHashMap<Object,Object>
implements PersistContext {
Impl() {
super(10);
}
@Override
public boolean add(Object entity) {
return put(entity,entity)==null;
}
}
return new Impl();
}
}

View File

@ -29,6 +29,6 @@ public interface PersistEventListener {
* *
* @param event The create event to be handled. * @param event The create event to be handled.
*/ */
void onPersist(PersistEvent event, Map createdAlready) throws HibernateException; void onPersist(PersistEvent event, PersistContext createdAlready) throws HibernateException;
} }

View File

@ -0,0 +1,38 @@
/*
* 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.spi;
import java.util.IdentityHashMap;
/**
* A {@link RefreshEvent} represents a {@linkplain org.hibernate.Session#refresh(Object) refresh operation}
* applied to a single entity. A {@code RefreshContext} is propagated across all cascaded refresh operations,
* and keeps track of all the entities we've already visited.
*
* @author Gavin King
*/
public interface RefreshContext {
boolean add(Object entity);
static RefreshContext create() {
// use extension to avoid creating
// a useless wrapper object
class Impl extends IdentityHashMap<Object,Object>
implements RefreshContext {
Impl() {
super(10);
}
@Override
public boolean add(Object entity) {
return put(entity,entity)==null;
}
}
return new Impl();
}
}

View File

@ -24,6 +24,6 @@ public interface RefreshEventListener {
*/ */
void onRefresh(RefreshEvent event) throws HibernateException; void onRefresh(RefreshEvent event) throws HibernateException;
void onRefresh(RefreshEvent event, Map refreshedAlready) throws HibernateException; void onRefresh(RefreshEvent event, RefreshContext refreshedAlready) throws HibernateException;
} }

View File

@ -69,6 +69,7 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.engine.spi.Status; import org.hibernate.engine.spi.Status;
import org.hibernate.engine.transaction.spi.TransactionImplementor; import org.hibernate.engine.transaction.spi.TransactionImplementor;
import org.hibernate.engine.transaction.spi.TransactionObserver; import org.hibernate.engine.transaction.spi.TransactionObserver;
import org.hibernate.event.spi.DeleteContext;
import org.hibernate.event.spi.MergeContext; import org.hibernate.event.spi.MergeContext;
import org.hibernate.event.spi.AutoFlushEvent; import org.hibernate.event.spi.AutoFlushEvent;
import org.hibernate.event.spi.AutoFlushEventListener; import org.hibernate.event.spi.AutoFlushEventListener;
@ -92,8 +93,10 @@ import org.hibernate.event.spi.LockEvent;
import org.hibernate.event.spi.LockEventListener; import org.hibernate.event.spi.LockEventListener;
import org.hibernate.event.spi.MergeEvent; import org.hibernate.event.spi.MergeEvent;
import org.hibernate.event.spi.MergeEventListener; import org.hibernate.event.spi.MergeEventListener;
import org.hibernate.event.spi.PersistContext;
import org.hibernate.event.spi.PersistEvent; import org.hibernate.event.spi.PersistEvent;
import org.hibernate.event.spi.PersistEventListener; import org.hibernate.event.spi.PersistEventListener;
import org.hibernate.event.spi.RefreshContext;
import org.hibernate.event.spi.RefreshEvent; import org.hibernate.event.spi.RefreshEvent;
import org.hibernate.event.spi.RefreshEventListener; import org.hibernate.event.spi.RefreshEventListener;
import org.hibernate.event.spi.ReplicateEvent; import org.hibernate.event.spi.ReplicateEvent;
@ -180,7 +183,8 @@ public class SessionImpl
implements SessionImplementor, LoadAccessContext, EventSource { implements SessionImplementor, LoadAccessContext, EventSource {
private static final EntityManagerMessageLogger log = HEMLogging.messageLogger( SessionImpl.class ); private static final EntityManagerMessageLogger log = HEMLogging.messageLogger( SessionImpl.class );
// Defaults to null which means the properties are the default - as defined in FastSessionServices#defaultSessionProperties // Defaults to null which means the properties are the default
// as defined in FastSessionServices#defaultSessionProperties
private Map<String, Object> properties; private Map<String, Object> properties;
private transient ActionQueue actionQueue; private transient ActionQueue actionQueue;
@ -191,7 +195,7 @@ public class SessionImpl
private LockOptions lockOptions; private LockOptions lockOptions;
private boolean autoClear; private boolean autoClear;
private boolean autoClose; private final boolean autoClose;
private transient LoadEvent loadEvent; //cached LoadEvent instance private transient LoadEvent loadEvent; //cached LoadEvent instance
@ -210,7 +214,8 @@ public class SessionImpl
if ( options instanceof SharedSessionCreationOptions ) { if ( options instanceof SharedSessionCreationOptions ) {
final SharedSessionCreationOptions sharedOptions = (SharedSessionCreationOptions) options; final SharedSessionCreationOptions sharedOptions = (SharedSessionCreationOptions) options;
final ActionQueue.TransactionCompletionProcesses transactionCompletionProcesses = sharedOptions.getTransactionCompletionProcesses(); final ActionQueue.TransactionCompletionProcesses transactionCompletionProcesses
= sharedOptions.getTransactionCompletionProcesses();
if ( sharedOptions.isTransactionCoordinatorShared() && transactionCompletionProcesses != null ) { if ( sharedOptions.isTransactionCoordinatorShared() && transactionCompletionProcesses != null ) {
actionQueue.setTransactionCompletionProcesses( actionQueue.setTransactionCompletionProcesses(
transactionCompletionProcesses, transactionCompletionProcesses,
@ -237,13 +242,12 @@ public class SessionImpl
// do not override explicitly set flush mode ( SessionBuilder#flushMode() ) // do not override explicitly set flush mode ( SessionBuilder#flushMode() )
if ( getHibernateFlushMode() == null ) { if ( getHibernateFlushMode() == null ) {
final FlushMode initialMode; final FlushMode initialMode = this.properties == null
if ( this.properties == null ) { ? fastSessionServices.initialSessionFlushMode
initialMode = fastSessionServices.initialSessionFlushMode; : ConfigurationHelper.getFlushMode(
} getSessionProperty(AvailableSettings.FLUSH_MODE),
else { FlushMode.AUTO
initialMode = ConfigurationHelper.getFlushMode( getSessionProperty( AvailableSettings.FLUSH_MODE ), FlushMode.AUTO ); );
}
setHibernateFlushMode( initialMode ); setHibernateFlushMode( initialMode );
} }
@ -264,7 +268,7 @@ public class SessionImpl
} }
if ( log.isTraceEnabled() ) { if ( log.isTraceEnabled() ) {
log.tracef( "Opened Session [%s] at timestamp: %s", getSessionIdentifier(), getTimestamp() ); log.tracef( "Opened Session [%s] at timestamp: %s", getSessionIdentifier(), getTransactionStartTimestamp() );
} }
} }
@ -358,7 +362,8 @@ public class SessionImpl
persistenceContext.clear(); persistenceContext.clear();
actionQueue.clear(); actionQueue.clear();
fastSessionServices.eventListenerGroup_CLEAR.fireLazyEventOnEachListener( this::createClearEvent, ClearEventListener::onClear ); fastSessionServices.eventListenerGroup_CLEAR
.fireLazyEventOnEachListener( this::createClearEvent, ClearEventListener::onClear );
} }
private ClearEvent createClearEvent() { private ClearEvent createClearEvent() {
@ -390,7 +395,7 @@ public class SessionImpl
// Original hibernate-entitymanager EM#close behavior // Original hibernate-entitymanager EM#close behavior
checkSessionFactoryOpen(); checkSessionFactoryOpen();
checkOpenOrWaitingForAutoClose(); checkOpenOrWaitingForAutoClose();
if ( fastSessionServices.discardOnClose || !isTransactionInProgress( false ) ) { if ( fastSessionServices.discardOnClose || !isTransactionInProgressAndNotMarkedForRollback() ) {
super.close(); super.close();
} }
else { else {
@ -408,13 +413,15 @@ public class SessionImpl
} }
} }
private boolean isTransactionInProgress(boolean isMarkedRollbackConsideredActive) { private boolean isTransactionInProgressAndNotMarkedForRollback() {
if ( waitingForAutoClose ) { if ( waitingForAutoClose ) {
return getSessionFactory().isOpen() && return getSessionFactory().isOpen()
getTransactionCoordinator().isTransactionActive( isMarkedRollbackConsideredActive ); && getTransactionCoordinator().isTransactionActive( false );
}
else {
return !isClosed()
&& getTransactionCoordinator().isTransactionActive( false );
} }
return !isClosed() &&
getTransactionCoordinator().isTransactionActive( isMarkedRollbackConsideredActive );
} }
@Override @Override
@ -578,8 +585,9 @@ public class SessionImpl
@Override @Override
public void delayedAfterCompletion() { public void delayedAfterCompletion() {
if ( getTransactionCoordinator() instanceof JtaTransactionCoordinatorImpl ) { TransactionCoordinator coordinator = getTransactionCoordinator();
( (JtaTransactionCoordinatorImpl) getTransactionCoordinator() ).getSynchronizationCallbackCoordinator() if ( coordinator instanceof JtaTransactionCoordinatorImpl ) {
( (JtaTransactionCoordinatorImpl) coordinator).getSynchronizationCallbackCoordinator()
.processAnyDelayedAfterCompletion(); .processAnyDelayedAfterCompletion();
} }
} }
@ -610,7 +618,8 @@ public class SessionImpl
checkOpen(); checkOpen();
checkTransactionSynchStatus(); checkTransactionSynchStatus();
checkNoUnresolvedActionsBeforeOperation(); checkNoUnresolvedActionsBeforeOperation();
fastSessionServices.eventListenerGroup_SAVE_UPDATE.fireEventOnEachListener( event, SaveOrUpdateEventListener::onSaveOrUpdate ); fastSessionServices.eventListenerGroup_SAVE_UPDATE
.fireEventOnEachListener( event, SaveOrUpdateEventListener::onSaveOrUpdate );
checkNoUnresolvedActionsAfterOperation(); checkNoUnresolvedActionsAfterOperation();
} }
@ -630,7 +639,8 @@ public class SessionImpl
checkOpen(); checkOpen();
checkTransactionSynchStatus(); checkTransactionSynchStatus();
checkNoUnresolvedActionsBeforeOperation(); checkNoUnresolvedActionsBeforeOperation();
fastSessionServices.eventListenerGroup_SAVE.fireEventOnEachListener( event, SaveOrUpdateEventListener::onSaveOrUpdate ); fastSessionServices.eventListenerGroup_SAVE
.fireEventOnEachListener( event, SaveOrUpdateEventListener::onSaveOrUpdate );
checkNoUnresolvedActionsAfterOperation(); checkNoUnresolvedActionsAfterOperation();
return event.getResultId(); return event.getResultId();
} }
@ -652,7 +662,8 @@ public class SessionImpl
checkOpen(); checkOpen();
checkTransactionSynchStatus(); checkTransactionSynchStatus();
checkNoUnresolvedActionsBeforeOperation(); checkNoUnresolvedActionsBeforeOperation();
fastSessionServices.eventListenerGroup_UPDATE.fireEventOnEachListener( event, SaveOrUpdateEventListener::onSaveOrUpdate ); fastSessionServices.eventListenerGroup_UPDATE
.fireEventOnEachListener( event, SaveOrUpdateEventListener::onSaveOrUpdate );
checkNoUnresolvedActionsAfterOperation(); checkNoUnresolvedActionsAfterOperation();
} }
@ -685,7 +696,8 @@ public class SessionImpl
private void fireLock(LockEvent event) { private void fireLock(LockEvent event) {
checkOpen(); checkOpen();
pulseTransactionCoordinator(); pulseTransactionCoordinator();
fastSessionServices.eventListenerGroup_LOCK.fireEventOnEachListener( event, LockEventListener::onLock ); fastSessionServices.eventListenerGroup_LOCK
.fireEventOnEachListener( event, LockEventListener::onLock );
delayedAfterCompletion(); delayedAfterCompletion();
} }
@ -704,7 +716,7 @@ public class SessionImpl
} }
@Override @Override
public void persist(String entityName, Object object, Map copiedAlready) throws HibernateException { public void persist(String entityName, Object object, PersistContext copiedAlready) throws HibernateException {
checkOpenOrWaitingForAutoClose(); checkOpenOrWaitingForAutoClose();
firePersist( copiedAlready, new PersistEvent( entityName, object, this ) ); firePersist( copiedAlready, new PersistEvent( entityName, object, this ) );
} }
@ -715,7 +727,8 @@ public class SessionImpl
checkTransactionSynchStatus(); checkTransactionSynchStatus();
checkNoUnresolvedActionsBeforeOperation(); checkNoUnresolvedActionsBeforeOperation();
fastSessionServices.eventListenerGroup_PERSIST.fireEventOnEachListener( event, PersistEventListener::onPersist ); fastSessionServices.eventListenerGroup_PERSIST
.fireEventOnEachListener( event, PersistEventListener::onPersist );
} }
catch (MappingException e) { catch (MappingException e) {
originalException = getExceptionConverter().convert( new IllegalArgumentException( e.getMessage() ) ); originalException = getExceptionConverter().convert( new IllegalArgumentException( e.getMessage() ) );
@ -751,7 +764,7 @@ public class SessionImpl
} }
} }
private void firePersist(final Map copiedAlready, final PersistEvent event) { private void firePersist(final PersistContext copiedAlready, final PersistEvent event) {
pulseTransactionCoordinator(); pulseTransactionCoordinator();
try { try {
@ -774,11 +787,12 @@ public class SessionImpl
// persistOnFlush() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // persistOnFlush() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override @Override
public void persistOnFlush(String entityName, Object object, Map copiedAlready) { public void persistOnFlush(String entityName, Object object, PersistContext copiedAlready) {
checkOpenOrWaitingForAutoClose(); checkOpenOrWaitingForAutoClose();
pulseTransactionCoordinator(); pulseTransactionCoordinator();
PersistEvent event = new PersistEvent( entityName, object, this ); PersistEvent event = new PersistEvent( entityName, object, this );
fastSessionServices.eventListenerGroup_PERSIST_ONFLUSH.fireEventOnEachListener( event, copiedAlready, PersistEventListener::onPersist ); fastSessionServices.eventListenerGroup_PERSIST_ONFLUSH
.fireEventOnEachListener( event, copiedAlready, PersistEventListener::onPersist );
delayedAfterCompletion(); delayedAfterCompletion();
} }
@ -806,7 +820,8 @@ public class SessionImpl
try { try {
checkTransactionSynchStatus(); checkTransactionSynchStatus();
checkNoUnresolvedActionsBeforeOperation(); checkNoUnresolvedActionsBeforeOperation();
fastSessionServices.eventListenerGroup_MERGE.fireEventOnEachListener( event, MergeEventListener::onMerge ); fastSessionServices.eventListenerGroup_MERGE
.fireEventOnEachListener( event, MergeEventListener::onMerge );
checkNoUnresolvedActionsAfterOperation(); checkNoUnresolvedActionsAfterOperation();
} }
catch ( ObjectDeletedException sse ) { catch ( ObjectDeletedException sse ) {
@ -826,7 +841,8 @@ public class SessionImpl
private void fireMerge(final MergeContext mergeContext, final MergeEvent event) { private void fireMerge(final MergeContext mergeContext, final MergeEvent event) {
try { try {
pulseTransactionCoordinator(); pulseTransactionCoordinator();
fastSessionServices.eventListenerGroup_MERGE.fireEventOnEachListener( event, mergeContext, MergeEventListener::onMerge ); fastSessionServices.eventListenerGroup_MERGE
.fireEventOnEachListener( event, mergeContext, MergeEventListener::onMerge );
} }
catch ( ObjectDeletedException sse ) { catch ( ObjectDeletedException sse ) {
throw getExceptionConverter().convert( new IllegalArgumentException( sse ) ); throw getExceptionConverter().convert( new IllegalArgumentException( sse ) );
@ -859,7 +875,7 @@ public class SessionImpl
} }
@Override @Override
public void delete(String entityName, Object object, boolean isCascadeDeleteEnabled, Set transientEntities) public void delete(String entityName, Object object, boolean isCascadeDeleteEnabled, DeleteContext transientEntities)
throws HibernateException { throws HibernateException {
checkOpenOrWaitingForAutoClose(); checkOpenOrWaitingForAutoClose();
final boolean removingOrphanBeforeUpates = persistenceContext.isRemovingOrphanBeforeUpates(); final boolean removingOrphanBeforeUpates = persistenceContext.isRemovingOrphanBeforeUpates();
@ -917,7 +933,8 @@ public class SessionImpl
private void fireDelete(final DeleteEvent event) { private void fireDelete(final DeleteEvent event) {
try{ try{
pulseTransactionCoordinator(); pulseTransactionCoordinator();
fastSessionServices.eventListenerGroup_DELETE.fireEventOnEachListener( event, DeleteEventListener::onDelete ); fastSessionServices.eventListenerGroup_DELETE
.fireEventOnEachListener( event, DeleteEventListener::onDelete );
} }
catch ( ObjectDeletedException sse ) { catch ( ObjectDeletedException sse ) {
throw getExceptionConverter().convert( new IllegalArgumentException( sse ) ); throw getExceptionConverter().convert( new IllegalArgumentException( sse ) );
@ -934,10 +951,11 @@ public class SessionImpl
} }
} }
private void fireDelete(final DeleteEvent event, final Set transientEntities) { private void fireDelete(final DeleteEvent event, final DeleteContext transientEntities) {
try{ try{
pulseTransactionCoordinator(); pulseTransactionCoordinator();
fastSessionServices.eventListenerGroup_DELETE.fireEventOnEachListener( event, transientEntities, DeleteEventListener::onDelete ); fastSessionServices.eventListenerGroup_DELETE
.fireEventOnEachListener( event, transientEntities, DeleteEventListener::onDelete );
} }
catch ( ObjectDeletedException sse ) { catch ( ObjectDeletedException sse ) {
throw getExceptionConverter().convert( new IllegalArgumentException( sse ) ); throw getExceptionConverter().convert( new IllegalArgumentException( sse ) );
@ -1215,13 +1233,15 @@ public class SessionImpl
// it seems they prevent these hot methods from being inlined. // it seems they prevent these hot methods from being inlined.
private void fireLoadNoChecks(final LoadEvent event, final LoadType loadType) { private void fireLoadNoChecks(final LoadEvent event, final LoadType loadType) {
pulseTransactionCoordinator(); pulseTransactionCoordinator();
fastSessionServices.eventListenerGroup_LOAD.fireEventOnEachListener( event, loadType, LoadEventListener::onLoad ); fastSessionServices.eventListenerGroup_LOAD
.fireEventOnEachListener( event, loadType, LoadEventListener::onLoad );
} }
private void fireResolveNaturalId(final ResolveNaturalIdEvent event) { private void fireResolveNaturalId(final ResolveNaturalIdEvent event) {
checkOpenOrWaitingForAutoClose(); checkOpenOrWaitingForAutoClose();
pulseTransactionCoordinator(); pulseTransactionCoordinator();
fastSessionServices.eventListenerGroup_RESOLVE_NATURAL_ID.fireEventOnEachListener( event, ResolveNaturalIdEventListener::onResolveNaturalId ); fastSessionServices.eventListenerGroup_RESOLVE_NATURAL_ID
.fireEventOnEachListener( event, ResolveNaturalIdEventListener::onResolveNaturalId );
delayedAfterCompletion(); delayedAfterCompletion();
} }
@ -1259,7 +1279,7 @@ public class SessionImpl
} }
@Override @Override
public void refresh(String entityName, Object object, Map refreshedAlready) throws HibernateException { public void refresh(String entityName, Object object, RefreshContext refreshedAlready) throws HibernateException {
checkOpenOrWaitingForAutoClose(); checkOpenOrWaitingForAutoClose();
fireRefresh( refreshedAlready, new RefreshEvent( entityName, object, this ) ); fireRefresh( refreshedAlready, new RefreshEvent( entityName, object, this ) );
} }
@ -1279,7 +1299,8 @@ public class SessionImpl
} }
} }
pulseTransactionCoordinator(); pulseTransactionCoordinator();
fastSessionServices.eventListenerGroup_REFRESH.fireEventOnEachListener( event, RefreshEventListener::onRefresh ); fastSessionServices.eventListenerGroup_REFRESH
.fireEventOnEachListener( event, RefreshEventListener::onRefresh );
} }
catch (RuntimeException e) { catch (RuntimeException e) {
if ( !getSessionFactory().getSessionFactoryOptions().isJpaBootstrap() ) { if ( !getSessionFactory().getSessionFactoryOptions().isJpaBootstrap() ) {
@ -1295,10 +1316,11 @@ public class SessionImpl
} }
} }
private void fireRefresh(final Map refreshedAlready, final RefreshEvent event) { private void fireRefresh(final RefreshContext refreshedAlready, final RefreshEvent event) {
try { try {
pulseTransactionCoordinator(); pulseTransactionCoordinator();
fastSessionServices.eventListenerGroup_REFRESH.fireEventOnEachListener( event, refreshedAlready, RefreshEventListener::onRefresh ); fastSessionServices.eventListenerGroup_REFRESH
.fireEventOnEachListener( event, refreshedAlready, RefreshEventListener::onRefresh );
} }
catch (RuntimeException e) { catch (RuntimeException e) {
throw getExceptionConverter().convert( e ); throw getExceptionConverter().convert( e );
@ -1325,7 +1347,8 @@ public class SessionImpl
private void fireReplicate(final ReplicateEvent event) { private void fireReplicate(final ReplicateEvent event) {
checkOpen(); checkOpen();
pulseTransactionCoordinator(); pulseTransactionCoordinator();
fastSessionServices.eventListenerGroup_REPLICATE.fireEventOnEachListener( event, ReplicateEventListener::onReplicate ); fastSessionServices.eventListenerGroup_REPLICATE
.fireEventOnEachListener( event, ReplicateEventListener::onReplicate );
delayedAfterCompletion(); delayedAfterCompletion();
} }
@ -1341,7 +1364,8 @@ public class SessionImpl
checkOpen(); checkOpen();
pulseTransactionCoordinator(); pulseTransactionCoordinator();
final EvictEvent event = new EvictEvent( object, this ); final EvictEvent event = new EvictEvent( object, this );
fastSessionServices.eventListenerGroup_EVICT.fireEventOnEachListener( event, EvictEventListener::onEvict ); fastSessionServices.eventListenerGroup_EVICT
.fireEventOnEachListener( event, EvictEventListener::onEvict );
delayedAfterCompletion(); delayedAfterCompletion();
} }
@ -1353,7 +1377,8 @@ public class SessionImpl
return false; return false;
} }
AutoFlushEvent event = new AutoFlushEvent( querySpaces, this ); AutoFlushEvent event = new AutoFlushEvent( querySpaces, this );
fastSessionServices.eventListenerGroup_AUTO_FLUSH.fireEventOnEachListener( event, AutoFlushEventListener::onAutoFlush ); fastSessionServices.eventListenerGroup_AUTO_FLUSH
.fireEventOnEachListener( event, AutoFlushEventListener::onAutoFlush );
return event.isFlushRequired(); return event.isFlushRequired();
} }
@ -1367,7 +1392,8 @@ public class SessionImpl
return true; return true;
} }
DirtyCheckEvent event = new DirtyCheckEvent( this ); DirtyCheckEvent event = new DirtyCheckEvent( this );
fastSessionServices.eventListenerGroup_DIRTY_CHECK.fireEventOnEachListener( event, DirtyCheckEventListener::onDirtyCheck ); fastSessionServices.eventListenerGroup_DIRTY_CHECK
.fireEventOnEachListener( event, DirtyCheckEventListener::onDirtyCheck );
delayedAfterCompletion(); delayedAfterCompletion();
return event.isDirty(); return event.isDirty();
} }
@ -1388,7 +1414,8 @@ public class SessionImpl
} }
FlushEvent event = new FlushEvent( this ); FlushEvent event = new FlushEvent( this );
fastSessionServices.eventListenerGroup_FLUSH.fireEventOnEachListener( event, FlushEventListener::onFlush ); fastSessionServices.eventListenerGroup_FLUSH
.fireEventOnEachListener( event, FlushEventListener::onFlush );
delayedAfterCompletion(); delayedAfterCompletion();
} }
catch ( RuntimeException e ) { catch ( RuntimeException e ) {
@ -1676,7 +1703,8 @@ public class SessionImpl
checkOpenOrWaitingForAutoClose(); checkOpenOrWaitingForAutoClose();
pulseTransactionCoordinator(); pulseTransactionCoordinator();
InitializeCollectionEvent event = new InitializeCollectionEvent( collection, this ); InitializeCollectionEvent event = new InitializeCollectionEvent( collection, this );
fastSessionServices.eventListenerGroup_INIT_COLLECTION.fireEventOnEachListener( event, InitializeCollectionEventListener::onInitializeCollection ); fastSessionServices.eventListenerGroup_INIT_COLLECTION
.fireEventOnEachListener( event, InitializeCollectionEventListener::onInitializeCollection );
delayedAfterCompletion(); delayedAfterCompletion();
} }
@ -2576,7 +2604,8 @@ public class SessionImpl
private Map<String, Object> computeCurrentSessionProperties() { private Map<String, Object> computeCurrentSessionProperties() {
final HashMap<String, Object> map = new HashMap<>( fastSessionServices.defaultSessionProperties ); final HashMap<String, Object> map = new HashMap<>( fastSessionServices.defaultSessionProperties );
//The FLUSH_MODE is always set at Session creation time, so it needs special treatment to not eagerly initialize this Map: //The FLUSH_MODE is always set at Session creation time,
//so it needs special treatment to not eagerly initialize this Map:
map.put( AvailableSettings.FLUSH_MODE, getHibernateFlushMode().name() ); map.put( AvailableSettings.FLUSH_MODE, getHibernateFlushMode().name() );
return map; return map;
} }

View File

@ -125,7 +125,7 @@ public interface ClassMetadata {
*/ */
@Deprecated(since = "5.3") @Deprecated(since = "5.3")
@SuppressWarnings({"UnusedDeclaration"}) @SuppressWarnings({"UnusedDeclaration"})
default Object[] getPropertyValuesToInsert(Object entity, Map mergeMap, SessionImplementor session) default Object[] getPropertyValuesToInsert(Object entity, Map<Object,Object> mergeMap, SessionImplementor session)
throws HibernateException { throws HibernateException {
return getPropertyValuesToInsert( entity, mergeMap, (SharedSessionContractImplementor) session ); return getPropertyValuesToInsert( entity, mergeMap, (SharedSessionContractImplementor) session );
} }
@ -134,7 +134,8 @@ public interface ClassMetadata {
* Return the values of the mapped properties of the object * Return the values of the mapped properties of the object
*/ */
@SuppressWarnings( {"UnusedDeclaration"}) @SuppressWarnings( {"UnusedDeclaration"})
Object[] getPropertyValuesToInsert(Object entity, Map mergeMap, SharedSessionContractImplementor session) throws HibernateException; Object[] getPropertyValuesToInsert(Object entity, Map<Object,Object> mergeMap, SharedSessionContractImplementor session)
throws HibernateException;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -144,7 +145,7 @@ public interface ClassMetadata {
/** /**
* The persistent class, or null * The persistent class, or null
*/ */
Class getMappedClass(); Class<?> getMappedClass();
/** /**
* Create a class instance initialized with the given identifier * Create a class instance initialized with the given identifier

View File

@ -5162,7 +5162,10 @@ public abstract class AbstractEntityPersister
} }
@Override @Override
public Object[] getPropertyValuesToInsert(Object entity, Map mergeMap, SharedSessionContractImplementor session) public Object[] getPropertyValuesToInsert(
Object entity,
Map<Object,Object> mergeMap,
SharedSessionContractImplementor session)
throws HibernateException { throws HibernateException {
if ( shouldGetAllProperties( entity ) && accessOptimizer != null ) { if ( shouldGetAllProperties( entity ) && accessOptimizer != null ) {
return accessOptimizer.getPropertyValues( entity ); return accessOptimizer.getPropertyValues( entity );

View File

@ -760,7 +760,7 @@ public interface EntityPersister
/** /**
* Return the values of the insertable properties of the object (including backrefs) * Return the values of the insertable properties of the object (including backrefs)
*/ */
Object[] getPropertyValuesToInsert(Object object, Map mergeMap, SharedSessionContractImplementor session); Object[] getPropertyValuesToInsert(Object object, Map<Object,Object> mergeMap, SharedSessionContractImplementor session);
/** /**
* Perform a select to retrieve the values of any generated properties * Perform a select to retrieve the values of any generated properties

View File

@ -6,8 +6,6 @@
*/ */
package org.hibernate.orm.test.events; package org.hibernate.orm.test.events;
import java.util.Set;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.SessionFactory; import org.hibernate.SessionFactory;
import org.hibernate.SessionFactoryObserver; import org.hibernate.SessionFactoryObserver;
@ -16,6 +14,7 @@ import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Configuration;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.event.service.spi.EventListenerRegistry; import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.DeleteContext;
import org.hibernate.event.spi.DeleteEvent; import org.hibernate.event.spi.DeleteEvent;
import org.hibernate.event.spi.DeleteEventListener; import org.hibernate.event.spi.DeleteEventListener;
import org.hibernate.event.spi.EventType; import org.hibernate.event.spi.EventType;
@ -135,7 +134,7 @@ public class CallbackTest extends BaseCoreFunctionalTestCase {
public void onDelete(DeleteEvent event) throws HibernateException { public void onDelete(DeleteEvent event) throws HibernateException {
} }
public void onDelete(DeleteEvent event, Set transientEntities) throws HibernateException { public void onDelete(DeleteEvent event, DeleteContext transientEntities) throws HibernateException {
} }
} }
} }

View File

@ -7,7 +7,6 @@
package org.hibernate.orm.test.jpa.model; package org.hibernate.orm.test.jpa.model;
import java.sql.Connection; import java.sql.Connection;
import java.util.IdentityHashMap;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.boot.Metadata; import org.hibernate.boot.Metadata;
@ -27,6 +26,7 @@ import org.hibernate.event.spi.AutoFlushEventListener;
import org.hibernate.event.spi.EventType; import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.FlushEntityEventListener; import org.hibernate.event.spi.FlushEntityEventListener;
import org.hibernate.event.spi.FlushEventListener; import org.hibernate.event.spi.FlushEventListener;
import org.hibernate.event.spi.PersistContext;
import org.hibernate.event.spi.PersistEventListener; import org.hibernate.event.spi.PersistEventListener;
import org.hibernate.integrator.spi.Integrator; import org.hibernate.integrator.spi.Integrator;
import org.hibernate.proxy.EntityNotFoundDelegate; import org.hibernate.proxy.EntityNotFoundDelegate;
@ -132,7 +132,7 @@ public abstract class AbstractJPATest extends BaseSessionFactoryFunctionalTest {
public static class JPAPersistOnFlushEventListener extends JPAPersistEventListener { public static class JPAPersistOnFlushEventListener extends JPAPersistEventListener {
@Override @Override
protected CascadingAction getCascadeAction() { protected CascadingAction<PersistContext> getCascadeAction() {
return CascadingActions.PERSIST_ON_FLUSH; return CascadingActions.PERSIST_ON_FLUSH;
} }
} }
@ -142,13 +142,13 @@ public abstract class AbstractJPATest extends BaseSessionFactoryFunctionalTest {
public static final AutoFlushEventListener INSTANCE = new JPAAutoFlushEventListener(); public static final AutoFlushEventListener INSTANCE = new JPAAutoFlushEventListener();
@Override @Override
protected CascadingAction getCascadingAction() { protected CascadingAction<PersistContext> getCascadingAction() {
return CascadingActions.PERSIST_ON_FLUSH; return CascadingActions.PERSIST_ON_FLUSH;
} }
@Override @Override
protected Object getAnything() { protected PersistContext getContext() {
return new IdentityHashMap( 10 ); return PersistContext.create();
} }
} }
@ -157,13 +157,13 @@ public abstract class AbstractJPATest extends BaseSessionFactoryFunctionalTest {
public static final FlushEventListener INSTANCE = new JPAFlushEventListener(); public static final FlushEventListener INSTANCE = new JPAFlushEventListener();
@Override @Override
protected CascadingAction getCascadingAction() { protected CascadingAction<PersistContext> getCascadingAction() {
return CascadingActions.PERSIST_ON_FLUSH; return CascadingActions.PERSIST_ON_FLUSH;
} }
@Override @Override
protected Object getAnything() { protected PersistContext getContext() {
return new IdentityHashMap( 10 ); return PersistContext.create();
} }
} }