HHH-9328 Avoids creation of Cascade objects at all

by converting all methods of the Cascade class into
static methods.
This commit is contained in:
Andrej Golovnin 2014-11-27 20:43:44 +01:00
parent 2105f2a49d
commit fb15ee548c
10 changed files with 130 additions and 53 deletions

View File

@ -58,22 +58,8 @@ import org.hibernate.type.Type;
public final class Cascade { public final class Cascade {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( Cascade.class ); private static final CoreMessageLogger LOG = CoreLogging.messageLogger( Cascade.class );
private int componentPathStackDepth = 0; private Cascade() {
private final CascadingAction action; // NOP
private final EventSource eventSource;
private CascadePoint cascadePoint;
/**
* Constructs a Cascade
*
* @param action The action we are cascading
* @param cascadePoint The point in the action at which we are trying to cascade currently
* @param eventSource The session
*/
public Cascade(final CascadingAction action, final CascadePoint cascadePoint, final EventSource eventSource) {
this.cascadePoint = cascadePoint;
this.eventSource = eventSource;
this.action = action;
} }
/** /**
@ -81,9 +67,13 @@ 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.
* @throws HibernateException
*/ */
public void cascade(final EntityPersister persister, final Object parent) { public static void cascade(
cascade( persister, parent, null ); final CascadingAction action, final CascadePoint cascadePoint,
final EventSource eventSource, final EntityPersister persister, final Object parent)
throws HibernateException {
cascade( action, cascadePoint, eventSource, persister, parent, null );
} }
/** /**
@ -95,9 +85,12 @@ 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 void cascade(final EntityPersister persister, final Object parent, final Object anything) { public static void cascade(
if ( persister.hasCascades() || action.requiresNoCascadeChecking() ) { final CascadingAction action, final CascadePoint cascadePoint,
// performance opt final EventSource eventSource, final EntityPersister persister, final Object parent, final Object anything)
throws HibernateException {
if ( persister.hasCascades() || action.requiresNoCascadeChecking() ) { // performance opt
final boolean traceEnabled = LOG.isTraceEnabled(); final boolean traceEnabled = LOG.isTraceEnabled();
if ( traceEnabled ) { if ( traceEnabled ) {
LOG.tracev( "Processing cascade {0} for: {1}", action, persister.getEntityName() ); LOG.tracev( "Processing cascade {0} for: {1}", action, persister.getEntityName() );
@ -106,6 +99,7 @@ public final class Cascade {
final Type[] types = persister.getPropertyTypes(); final Type[] types = persister.getPropertyTypes();
final CascadeStyle[] cascadeStyles = persister.getPropertyCascadeStyles(); final CascadeStyle[] cascadeStyles = persister.getPropertyCascadeStyles();
final boolean hasUninitializedLazyProperties = persister.hasUninitializedLazyProperties( parent ); final boolean hasUninitializedLazyProperties = persister.hasUninitializedLazyProperties( parent );
final int componentPathStackDepth = 0;
for ( int i=0; i<types.length; i++) { for ( int i=0; i<types.length; i++) {
final CascadeStyle style = cascadeStyles[i]; final CascadeStyle style = cascadeStyles[i];
final String propertyName = persister.getPropertyNames()[i]; final String propertyName = persister.getPropertyNames()[i];
@ -116,6 +110,10 @@ public final class Cascade {
if ( style.doCascade( action ) ) { if ( style.doCascade( action ) ) {
cascadeProperty( cascadeProperty(
action,
cascadePoint,
eventSource,
componentPathStackDepth,
parent, parent,
persister.getPropertyValue( parent, i ), persister.getPropertyValue( parent, i ),
types[i], types[i],
@ -145,7 +143,11 @@ public final class Cascade {
/** /**
* Cascade an action to the child or children * Cascade an action to the child or children
*/ */
private void cascadeProperty( private static void cascadeProperty(
final CascadingAction action,
final CascadePoint cascadePoint,
final EventSource eventSource,
final int componentPathStackDepth,
final Object parent, final Object parent,
final Object child, final Object child,
final Type type, final Type type,
@ -157,8 +159,12 @@ public final class Cascade {
if ( child != null ) { if ( child != null ) {
if ( type.isAssociationType() ) { if ( type.isAssociationType() ) {
final AssociationType associationType = (AssociationType) type; final AssociationType associationType = (AssociationType) type;
if ( cascadeAssociationNow( associationType ) ) { if ( cascadeAssociationNow( cascadePoint, associationType ) ) {
cascadeAssociation( cascadeAssociation(
action,
cascadePoint,
eventSource,
componentPathStackDepth,
parent, parent,
child, child,
type, type,
@ -169,7 +175,17 @@ public final class Cascade {
} }
} }
else if ( type.isComponentType() ) { else if ( type.isComponentType() ) {
cascadeComponent( parent, child, (CompositeType) type, propertyName, anything ); cascadeComponent(
action,
cascadePoint,
eventSource,
componentPathStackDepth,
parent,
child,
(CompositeType) type,
propertyName,
anything
);
} }
} }
@ -247,21 +263,25 @@ public final class Cascade {
* *
* @return True if the attribute represents a logical one to one association * @return True if the attribute represents a logical one to one association
*/ */
private boolean isLogicalOneToOne(Type type) { private static boolean isLogicalOneToOne(Type type) {
return type.isEntityType() && ( (EntityType) type ).isLogicalOneToOne(); return type.isEntityType() && ( (EntityType) type ).isLogicalOneToOne();
} }
private boolean cascadeAssociationNow(AssociationType associationType) { private static boolean cascadeAssociationNow(final CascadePoint cascadePoint, AssociationType associationType) {
return associationType.getForeignKeyDirection().cascadeNow( cascadePoint ); return associationType.getForeignKeyDirection().cascadeNow( cascadePoint );
} }
private void cascadeComponent( private static void cascadeComponent(
final CascadingAction action,
final CascadePoint cascadePoint,
final EventSource eventSource,
final int componentPathStackDepth,
final Object parent, final Object parent,
final Object child, final Object child,
final CompositeType componentType, final CompositeType componentType,
final String componentPropertyName, final String componentPropertyName,
final Object anything) { final Object anything) {
componentPathStackDepth++;
final Object[] children = componentType.getPropertyValues( child, eventSource ); final Object[] children = componentType.getPropertyValues( child, eventSource );
final Type[] types = componentType.getSubtypes(); final Type[] types = componentType.getSubtypes();
for ( int i=0; i<types.length; i++ ) { for ( int i=0; i<types.length; i++ ) {
@ -269,6 +289,10 @@ public final class Cascade {
final String subPropertyName = componentType.getPropertyNames()[i]; final String subPropertyName = componentType.getPropertyNames()[i];
if ( componentPropertyStyle.doCascade( action ) ) { if ( componentPropertyStyle.doCascade( action ) ) {
cascadeProperty( cascadeProperty(
action,
cascadePoint,
eventSource,
componentPathStackDepth + 1,
parent, parent,
children[i], children[i],
types[i], types[i],
@ -279,10 +303,13 @@ public final class Cascade {
); );
} }
} }
componentPathStackDepth--;
} }
private void cascadeAssociation( private static void cascadeAssociation(
final CascadingAction action,
final CascadePoint cascadePoint,
final EventSource eventSource,
final int componentPathStackDepth,
final Object parent, final Object parent,
final Object child, final Object child,
final Type type, final Type type,
@ -290,17 +317,31 @@ public final class Cascade {
final Object anything, final Object anything,
final boolean isCascadeDeleteEnabled) { final boolean isCascadeDeleteEnabled) {
if ( type.isEntityType() || type.isAnyType() ) { if ( type.isEntityType() || type.isAnyType() ) {
cascadeToOne( parent, child, type, style, anything, isCascadeDeleteEnabled ); cascadeToOne( action, eventSource, parent, child, type, style, anything, isCascadeDeleteEnabled );
} }
else if ( type.isCollectionType() ) { else if ( type.isCollectionType() ) {
cascadeCollection( parent, child, style, anything, (CollectionType) type ); cascadeCollection(
action,
cascadePoint,
eventSource,
componentPathStackDepth,
parent,
child,
style,
anything,
(CollectionType) type
);
} }
} }
/** /**
* Cascade an action to a collection * Cascade an action to a collection
*/ */
private void cascadeCollection( private static void cascadeCollection(
final CascadingAction action,
final CascadePoint cascadePoint,
final EventSource eventSource,
final int componentPathStackDepth,
final Object parent, final Object parent,
final Object child, final Object child,
final CascadeStyle style, final CascadeStyle style,
@ -309,14 +350,18 @@ public final class Cascade {
final CollectionPersister persister = eventSource.getFactory().getCollectionPersister( type.getRole() ); final CollectionPersister persister = eventSource.getFactory().getCollectionPersister( type.getRole() );
final Type elemType = persister.getElementType(); final Type elemType = persister.getElementType();
final CascadePoint originalCascadePoint = cascadePoint; CascadePoint elementsCascadePoint = cascadePoint;
if ( cascadePoint == CascadePoint.AFTER_INSERT_BEFORE_DELETE) { if ( cascadePoint == CascadePoint.AFTER_INSERT_BEFORE_DELETE ) {
cascadePoint = CascadePoint.AFTER_INSERT_BEFORE_DELETE_VIA_COLLECTION; elementsCascadePoint = CascadePoint.AFTER_INSERT_BEFORE_DELETE_VIA_COLLECTION;
} }
//cascade to current collection elements //cascade to current collection elements
if ( elemType.isEntityType() || elemType.isAnyType() || elemType.isComponentType() ) { if ( elemType.isEntityType() || elemType.isAnyType() || elemType.isComponentType() ) {
cascadeCollectionElements( cascadeCollectionElements(
action,
elementsCascadePoint,
eventSource,
componentPathStackDepth,
parent, parent,
child, child,
type, type,
@ -326,14 +371,14 @@ public final class Cascade {
persister.isCascadeDeleteEnabled() persister.isCascadeDeleteEnabled()
); );
} }
cascadePoint = originalCascadePoint;
} }
/** /**
* Cascade an action to a to-one association or any type * Cascade an action to a to-one association or any type
*/ */
private void cascadeToOne( private static void cascadeToOne(
final CascadingAction action,
final EventSource eventSource,
final Object parent, final Object parent,
final Object child, final Object child,
final Type type, final Type type,
@ -358,7 +403,11 @@ public final class Cascade {
/** /**
* Cascade to the collection elements * Cascade to the collection elements
*/ */
private void cascadeCollectionElements( private static void cascadeCollectionElements(
final CascadingAction action,
final CascadePoint cascadePoint,
final EventSource eventSource,
final int componentPathStackDepth,
final Object parent, final Object parent,
final Object child, final Object child,
final CollectionType collectionType, final CollectionType collectionType,
@ -377,6 +426,10 @@ public final class Cascade {
final Iterator itr = action.getCascadableChildrenIterator( eventSource, collectionType, child ); final Iterator itr = action.getCascadableChildrenIterator( eventSource, collectionType, child );
while ( itr.hasNext() ) { while ( itr.hasNext() ) {
cascadeProperty( cascadeProperty(
action,
cascadePoint,
eventSource,
componentPathStackDepth,
parent, parent,
itr.next(), itr.next(),
elemType, elemType,
@ -407,7 +460,7 @@ public final class Cascade {
// 1. newly instantiated collections // 1. newly instantiated collections
// 2. arrays (we can't track orphans for detached arrays) // 2. arrays (we can't track orphans for detached arrays)
final String entityName = collectionType.getAssociatedEntityName( eventSource.getFactory() ); final String entityName = collectionType.getAssociatedEntityName( eventSource.getFactory() );
deleteOrphans( entityName, (PersistentCollection) child ); deleteOrphans( eventSource, entityName, (PersistentCollection) child );
if ( traceEnabled ) { if ( traceEnabled ) {
LOG.tracev( "Done deleting orphans for collection: {0}", collectionType.getRole() ); LOG.tracev( "Done deleting orphans for collection: {0}", collectionType.getRole() );
@ -418,7 +471,7 @@ public final class Cascade {
/** /**
* Delete any entities that were removed from the collection * Delete any entities that were removed from the collection
*/ */
private void deleteOrphans(String entityName, PersistentCollection pc) throws HibernateException { private static void deleteOrphans(EventSource eventSource, String entityName, PersistentCollection pc) throws HibernateException {
//TODO: suck this logic into the collection! //TODO: suck this logic into the collection!
final Collection orphans; final Collection orphans;
if ( pc.wasInitialized() ) { if ( pc.wasInitialized() ) {

View File

@ -164,7 +164,7 @@ public abstract class AbstractFlushingEventListener implements Serializable {
throws HibernateException { throws HibernateException {
session.getPersistenceContext().incrementCascadeLevel(); session.getPersistenceContext().incrementCascadeLevel();
try { try {
new Cascade( getCascadingAction(), CascadePoint.BEFORE_FLUSH, session ).cascade( persister, object, anything ); Cascade.cascade( getCascadingAction(), CascadePoint.BEFORE_FLUSH, session, persister, object, anything );
} }
finally { finally {
session.getPersistenceContext().decrementCascadeLevel(); session.getPersistenceContext().decrementCascadeLevel();

View File

@ -429,7 +429,10 @@ public abstract class AbstractSaveEventListener extends AbstractReassociateEvent
// cascade-save to many-to-one BEFORE the parent is saved // cascade-save to many-to-one BEFORE the parent is saved
source.getPersistenceContext().incrementCascadeLevel(); source.getPersistenceContext().incrementCascadeLevel();
try { try {
new Cascade( getCascadeAction(), CascadePoint.BEFORE_INSERT_AFTER_DELETE, source ).cascade( Cascade.cascade(
getCascadeAction(),
CascadePoint.BEFORE_INSERT_AFTER_DELETE,
source,
persister, persister,
entity, entity,
anything anything
@ -457,7 +460,10 @@ public abstract class AbstractSaveEventListener extends AbstractReassociateEvent
// cascade-save to collections AFTER the collection owner was saved // cascade-save to collections AFTER the collection owner was saved
source.getPersistenceContext().incrementCascadeLevel(); source.getPersistenceContext().incrementCascadeLevel();
try { try {
new Cascade( getCascadeAction(), CascadePoint.AFTER_INSERT_BEFORE_DELETE, source ).cascade( Cascade.cascade(
getCascadeAction(),
CascadePoint.AFTER_INSERT_BEFORE_DELETE,
source,
persister, persister,
entity, entity,
anything anything

View File

@ -350,7 +350,10 @@ public class DefaultDeleteEventListener implements DeleteEventListener {
session.getPersistenceContext().incrementCascadeLevel(); session.getPersistenceContext().incrementCascadeLevel();
try { try {
// cascade-delete to collections BEFORE the collection owner is deleted // cascade-delete to collections BEFORE the collection owner is deleted
new Cascade( CascadingActions.DELETE, CascadePoint.AFTER_INSERT_BEFORE_DELETE, session ).cascade( Cascade.cascade(
CascadingActions.DELETE,
CascadePoint.AFTER_INSERT_BEFORE_DELETE,
session,
persister, persister,
entity, entity,
transientEntities transientEntities
@ -373,7 +376,10 @@ public class DefaultDeleteEventListener implements DeleteEventListener {
session.getPersistenceContext().incrementCascadeLevel(); session.getPersistenceContext().incrementCascadeLevel();
try { try {
// cascade-delete to many-to-one AFTER the parent was deleted // cascade-delete to many-to-one AFTER the parent was deleted
new Cascade( CascadingActions.DELETE, CascadePoint.BEFORE_INSERT_AFTER_DELETE, session ).cascade( Cascade.cascade(
CascadingActions.DELETE,
CascadePoint.BEFORE_INSERT_AFTER_DELETE,
session,
persister, persister,
entity, entity,
transientEntities transientEntities

View File

@ -145,6 +145,6 @@ public class DefaultEvictEventListener implements EvictEventListener {
// This is now handled by removeEntity() // This is now handled by removeEntity()
//session.getPersistenceContext().removeDatabaseSnapshot(key); //session.getPersistenceContext().removeDatabaseSnapshot(key);
new Cascade( CascadingActions.EVICT, CascadePoint.AFTER_EVICT, session ).cascade( persister, object ); Cascade.cascade( CascadingActions.EVICT, CascadePoint.AFTER_EVICT, session, persister, object );
} }
} }

View File

@ -103,7 +103,10 @@ public class DefaultLockEventListener extends AbstractLockUpgradeEventListener i
EventSource source = event.getSession(); EventSource source = event.getSession();
source.getPersistenceContext().incrementCascadeLevel(); source.getPersistenceContext().incrementCascadeLevel();
try { try {
new Cascade( CascadingActions.LOCK, CascadePoint.AFTER_LOCK, source).cascade( Cascade.cascade(
CascadingActions.LOCK,
CascadePoint.AFTER_LOCK,
source,
persister, persister,
entity, entity,
event.getLockOptions() event.getLockOptions()

View File

@ -471,7 +471,10 @@ public class DefaultMergeEventListener extends AbstractSaveEventListener impleme
) { ) {
source.getPersistenceContext().incrementCascadeLevel(); source.getPersistenceContext().incrementCascadeLevel();
try { try {
new Cascade( getCascadeAction(), CascadePoint.BEFORE_MERGE, source ).cascade( Cascade.cascade(
getCascadeAction(),
CascadePoint.BEFORE_MERGE,
source,
persister, persister,
entity, entity,
copyCache copyCache

View File

@ -135,7 +135,10 @@ 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 ); refreshedAlready.put( object, object );
new Cascade( CascadingActions.REFRESH, CascadePoint.BEFORE_REFRESH, source ).cascade( Cascade.cascade(
CascadingActions.REFRESH,
CascadePoint.BEFORE_REFRESH,
source,
persister, persister,
object, object,
refreshedAlready refreshedAlready

View File

@ -222,7 +222,10 @@ public class DefaultReplicateEventListener extends AbstractSaveEventListener imp
EventSource source) { EventSource source) {
source.getPersistenceContext().incrementCascadeLevel(); source.getPersistenceContext().incrementCascadeLevel();
try { try {
new Cascade( CascadingActions.REPLICATE, CascadePoint.AFTER_UPDATE, source ).cascade( Cascade.cascade(
CascadingActions.REPLICATE,
CascadePoint.AFTER_UPDATE,
source,
persister, persister,
entity, entity,
replicationMode replicationMode

View File

@ -372,7 +372,7 @@ public class DefaultSaveOrUpdateEventListener extends AbstractSaveEventListener
final EventSource source = event.getSession(); final EventSource source = event.getSession();
source.getPersistenceContext().incrementCascadeLevel(); source.getPersistenceContext().incrementCascadeLevel();
try { try {
new Cascade( CascadingActions.SAVE_UPDATE, CascadePoint.AFTER_UPDATE, source ).cascade( persister, entity ); Cascade.cascade( CascadingActions.SAVE_UPDATE, CascadePoint.AFTER_UPDATE, source, persister, entity );
} }
finally { finally {
source.getPersistenceContext().decrementCascadeLevel(); source.getPersistenceContext().decrementCascadeLevel();