Merge pull request #848 from golovnin/HHH-9328_newmaster

HHH-9328 Avoid creation of Cascade objects at all
This commit is contained in:
Steve Ebersole 2015-03-10 22:21:53 -05:00
commit 24bafba2b0
10 changed files with 130 additions and 53 deletions

View File

@ -58,22 +58,8 @@ import org.hibernate.type.Type;
public final class Cascade {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( Cascade.class );
private int componentPathStackDepth = 0;
private final CascadingAction action;
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;
private Cascade() {
// NOP
}
/**
@ -81,9 +67,13 @@ public final class Cascade {
*
* @param persister The parent's entity persister
* @param parent The parent reference.
* @throws HibernateException
*/
public void cascade(final EntityPersister persister, final Object parent) {
cascade( persister, parent, null );
public static void cascade(
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
* which is specific to each CascadingAction type
*/
public void cascade(final EntityPersister persister, final Object parent, final Object anything) {
if ( persister.hasCascades() || action.requiresNoCascadeChecking() ) {
// performance opt
public static void cascade(
final CascadingAction action, final CascadePoint cascadePoint,
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();
if ( traceEnabled ) {
LOG.tracev( "Processing cascade {0} for: {1}", action, persister.getEntityName() );
@ -106,6 +99,7 @@ public final class Cascade {
final Type[] types = persister.getPropertyTypes();
final CascadeStyle[] cascadeStyles = persister.getPropertyCascadeStyles();
final boolean hasUninitializedLazyProperties = persister.hasUninitializedLazyProperties( parent );
final int componentPathStackDepth = 0;
for ( int i=0; i<types.length; i++) {
final CascadeStyle style = cascadeStyles[i];
final String propertyName = persister.getPropertyNames()[i];
@ -116,6 +110,10 @@ public final class Cascade {
if ( style.doCascade( action ) ) {
cascadeProperty(
action,
cascadePoint,
eventSource,
componentPathStackDepth,
parent,
persister.getPropertyValue( parent, i ),
types[i],
@ -145,7 +143,11 @@ public final class Cascade {
/**
* 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 child,
final Type type,
@ -157,8 +159,12 @@ public final class Cascade {
if ( child != null ) {
if ( type.isAssociationType() ) {
final AssociationType associationType = (AssociationType) type;
if ( cascadeAssociationNow( associationType ) ) {
if ( cascadeAssociationNow( cascadePoint, associationType ) ) {
cascadeAssociation(
action,
cascadePoint,
eventSource,
componentPathStackDepth,
parent,
child,
type,
@ -169,7 +175,17 @@ public final class Cascade {
}
}
else if ( type.isComponentType() ) {
cascadeComponent( parent, child, (CompositeType) type, propertyName, anything );
cascadeComponent(
action,
cascadePoint,
eventSource,
componentPathStackDepth,
parent,
child,
(CompositeType) type,
propertyName,
anything
);
}
}
@ -248,21 +264,25 @@ public final class Cascade {
*
* @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();
}
private boolean cascadeAssociationNow(AssociationType associationType) {
private static boolean cascadeAssociationNow(final CascadePoint cascadePoint, AssociationType associationType) {
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 child,
final CompositeType componentType,
final String componentPropertyName,
final Object anything) {
componentPathStackDepth++;
final Object[] children = componentType.getPropertyValues( child, eventSource );
final Type[] types = componentType.getSubtypes();
for ( int i=0; i<types.length; i++ ) {
@ -270,6 +290,10 @@ public final class Cascade {
final String subPropertyName = componentType.getPropertyNames()[i];
if ( componentPropertyStyle.doCascade( action ) ) {
cascadeProperty(
action,
cascadePoint,
eventSource,
componentPathStackDepth + 1,
parent,
children[i],
types[i],
@ -280,10 +304,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 child,
final Type type,
@ -291,17 +318,31 @@ public final class Cascade {
final Object anything,
final boolean isCascadeDeleteEnabled) {
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() ) {
cascadeCollection( parent, child, style, anything, (CollectionType) type );
cascadeCollection(
action,
cascadePoint,
eventSource,
componentPathStackDepth,
parent,
child,
style,
anything,
(CollectionType) type
);
}
}
/**
* 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 child,
final CascadeStyle style,
@ -310,14 +351,18 @@ public final class Cascade {
final CollectionPersister persister = eventSource.getFactory().getCollectionPersister( type.getRole() );
final Type elemType = persister.getElementType();
final CascadePoint originalCascadePoint = cascadePoint;
if ( cascadePoint == CascadePoint.AFTER_INSERT_BEFORE_DELETE) {
cascadePoint = CascadePoint.AFTER_INSERT_BEFORE_DELETE_VIA_COLLECTION;
CascadePoint elementsCascadePoint = cascadePoint;
if ( cascadePoint == CascadePoint.AFTER_INSERT_BEFORE_DELETE ) {
elementsCascadePoint = CascadePoint.AFTER_INSERT_BEFORE_DELETE_VIA_COLLECTION;
}
//cascade to current collection elements
if ( elemType.isEntityType() || elemType.isAnyType() || elemType.isComponentType() ) {
cascadeCollectionElements(
action,
elementsCascadePoint,
eventSource,
componentPathStackDepth,
parent,
child,
type,
@ -327,14 +372,14 @@ public final class Cascade {
persister.isCascadeDeleteEnabled()
);
}
cascadePoint = originalCascadePoint;
}
/**
* 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 child,
final Type type,
@ -359,7 +404,11 @@ public final class Cascade {
/**
* 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 child,
final CollectionType collectionType,
@ -378,6 +427,10 @@ public final class Cascade {
final Iterator itr = action.getCascadableChildrenIterator( eventSource, collectionType, child );
while ( itr.hasNext() ) {
cascadeProperty(
action,
cascadePoint,
eventSource,
componentPathStackDepth,
parent,
itr.next(),
elemType,
@ -408,7 +461,7 @@ public final class Cascade {
// 1. newly instantiated collections
// 2. arrays (we can't track orphans for detached arrays)
final String entityName = collectionType.getAssociatedEntityName( eventSource.getFactory() );
deleteOrphans( entityName, (PersistentCollection) child );
deleteOrphans( eventSource, entityName, (PersistentCollection) child );
if ( traceEnabled ) {
LOG.tracev( "Done deleting orphans for collection: {0}", collectionType.getRole() );
@ -419,7 +472,7 @@ public final class Cascade {
/**
* 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!
final Collection orphans;
if ( pc.wasInitialized() ) {

View File

@ -164,7 +164,7 @@ public abstract class AbstractFlushingEventListener implements Serializable {
throws HibernateException {
session.getPersistenceContext().incrementCascadeLevel();
try {
new Cascade( getCascadingAction(), CascadePoint.BEFORE_FLUSH, session ).cascade( persister, object, anything );
Cascade.cascade( getCascadingAction(), CascadePoint.BEFORE_FLUSH, session, persister, object, anything );
}
finally {
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
source.getPersistenceContext().incrementCascadeLevel();
try {
new Cascade( getCascadeAction(), CascadePoint.BEFORE_INSERT_AFTER_DELETE, source ).cascade(
Cascade.cascade(
getCascadeAction(),
CascadePoint.BEFORE_INSERT_AFTER_DELETE,
source,
persister,
entity,
anything
@ -457,7 +460,10 @@ public abstract class AbstractSaveEventListener extends AbstractReassociateEvent
// cascade-save to collections AFTER the collection owner was saved
source.getPersistenceContext().incrementCascadeLevel();
try {
new Cascade( getCascadeAction(), CascadePoint.AFTER_INSERT_BEFORE_DELETE, source ).cascade(
Cascade.cascade(
getCascadeAction(),
CascadePoint.AFTER_INSERT_BEFORE_DELETE,
source,
persister,
entity,
anything

View File

@ -350,7 +350,10 @@ public class DefaultDeleteEventListener implements DeleteEventListener {
session.getPersistenceContext().incrementCascadeLevel();
try {
// 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,
entity,
transientEntities
@ -373,7 +376,10 @@ public class DefaultDeleteEventListener implements DeleteEventListener {
session.getPersistenceContext().incrementCascadeLevel();
try {
// 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,
entity,
transientEntities

View File

@ -145,6 +145,6 @@ public class DefaultEvictEventListener implements EvictEventListener {
// This is now handled by removeEntity()
//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();
source.getPersistenceContext().incrementCascadeLevel();
try {
new Cascade( CascadingActions.LOCK, CascadePoint.AFTER_LOCK, source).cascade(
Cascade.cascade(
CascadingActions.LOCK,
CascadePoint.AFTER_LOCK,
source,
persister,
entity,
event.getLockOptions()

View File

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

View File

@ -135,7 +135,10 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
// cascade the refresh prior to refreshing this entity
refreshedAlready.put( object, object );
new Cascade( CascadingActions.REFRESH, CascadePoint.BEFORE_REFRESH, source ).cascade(
Cascade.cascade(
CascadingActions.REFRESH,
CascadePoint.BEFORE_REFRESH,
source,
persister,
object,
refreshedAlready

View File

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

View File

@ -372,7 +372,7 @@ public class DefaultSaveOrUpdateEventListener extends AbstractSaveEventListener
final EventSource source = event.getSession();
source.getPersistenceContext().incrementCascadeLevel();
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 {
source.getPersistenceContext().decrementCascadeLevel();