Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HHH-9328 Avoid creation of Cascade objects at all #779

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -58,32 +58,22 @@
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
}

/**
* Cascade an action from the parent entity instance to all its children.
*
* @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 );
}

/**
Expand All @@ -95,9 +85,12 @@ public void cascade(final EntityPersister persister, final Object parent) {
* @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() );
Expand All @@ -106,6 +99,7 @@ public void cascade(final EntityPersister persister, final Object parent, final
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];
Expand All @@ -116,6 +110,10 @@ public void cascade(final EntityPersister persister, final Object parent, final

if ( style.doCascade( action ) ) {
cascadeProperty(
action,
cascadePoint,
eventSource,
componentPathStackDepth,
parent,
persister.getPropertyValue( parent, i ),
types[i],
Expand Down Expand Up @@ -145,7 +143,11 @@ else if ( action.requiresNoCascadeChecking() ) {
/**
* 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,
Expand All @@ -157,8 +159,12 @@ private void cascadeProperty(
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,
Expand All @@ -169,7 +175,17 @@ private void cascadeProperty(
}
}
else if ( type.isComponentType() ) {
cascadeComponent( parent, child, (CompositeType) type, propertyName, anything );
cascadeComponent(
action,
cascadePoint,
eventSource,
componentPathStackDepth,
parent,
child,
(CompositeType) type,
propertyName,
anything
);
}
}

Expand Down Expand Up @@ -247,28 +263,36 @@ else if ( type.isComponentType() ) {
*
* @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++ ) {
final CascadeStyle componentPropertyStyle = componentType.getCascadeStyle( i );
final String subPropertyName = componentType.getPropertyNames()[i];
if ( componentPropertyStyle.doCascade( action ) ) {
cascadeProperty(
action,
cascadePoint,
eventSource,
componentPathStackDepth + 1,
parent,
children[i],
types[i],
Expand All @@ -279,28 +303,45 @@ private void cascadeComponent(
);
}
}
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,
final CascadeStyle style,
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,
Expand All @@ -309,14 +350,18 @@ private void cascadeCollection(
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,
Expand All @@ -326,14 +371,14 @@ private void cascadeCollection(
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,
Expand All @@ -358,7 +403,11 @@ private void cascadeToOne(
/**
* 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,
Expand All @@ -377,6 +426,10 @@ private void cascadeCollectionElements(
final Iterator itr = action.getCascadableChildrenIterator( eventSource, collectionType, child );
while ( itr.hasNext() ) {
cascadeProperty(
action,
cascadePoint,
eventSource,
componentPathStackDepth,
parent,
itr.next(),
elemType,
Expand Down Expand Up @@ -407,7 +460,7 @@ private void cascadeCollectionElements(
// 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() );
Expand All @@ -418,7 +471,7 @@ private void cascadeCollectionElements(
/**
* 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() ) {
Expand Down
Expand Up @@ -164,7 +164,7 @@ private void cascadeOnFlush(EventSource session, EntityPersister persister, Obje
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();
Expand Down
Expand Up @@ -429,7 +429,10 @@ protected void cascadeBeforeSave(
// 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
Expand Down Expand Up @@ -457,7 +460,10 @@ protected void cascadeAfterSave(
// 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
Expand Down
Expand Up @@ -350,7 +350,10 @@ protected void cascadeBeforeDelete(
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
Expand All @@ -373,7 +376,10 @@ protected void cascadeAfterDelete(
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
Expand Down
Expand Up @@ -145,6 +145,6 @@ protected void doEvict(
// 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 );
}
}
Expand Up @@ -103,7 +103,10 @@ private void cascadeOnLock(LockEvent event, EntityPersister persister, Object en
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()
Expand Down
Expand Up @@ -471,7 +471,10 @@ protected void cascadeOnMerge(
) {
source.getPersistenceContext().incrementCascadeLevel();
try {
new Cascade( getCascadeAction(), CascadePoint.BEFORE_MERGE, source ).cascade(
Cascade.cascade(
getCascadeAction(),
CascadePoint.BEFORE_MERGE,
source,
persister,
entity,
copyCache
Expand Down
Expand Up @@ -135,7 +135,10 @@ public void onRefresh(RefreshEvent event, Map refreshedAlready) {

// 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
Expand Down