diff --git a/hibernate-core/src/main/java/org/hibernate/engine/internal/Cascade.java b/hibernate-core/src/main/java/org/hibernate/engine/internal/Cascade.java index 284686e69b..8f22674c34 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/internal/Cascade.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/internal/Cascade.java @@ -93,15 +93,30 @@ public final class Cascade { if ( style.doCascade( action ) ) { Object child; - // For bytecode enhanced entities, need to fetch the attribute - if ( hasUninitializedLazyProperties && persister.getPropertyLaziness()[i] && action.performOnLazyProperty() ) { + if ( hasUninitializedLazyProperties && + !persister.getInstrumentationMetadata().isAttributeLoaded( parent, propertyName ) ) { + // parent is a bytecode enhanced entity. + // cascading to an uninitialized, lazy value. if ( types[i].isCollectionType() ) { + // The collection does not need to be loaded from the DB. + // CollectionType#resolve will return an uninitialized PersistentCollection. + // The action will initialize the collection later, if necessary. child = types[i].resolve( LazyPropertyInitializer.UNFETCHED_PROPERTY, eventSource, parent ); + // TODO: it would be nice to be able to set the attribute in parent using + // persister.setPropertyValue( parent, i, child ). + // Unfortunately, that would cause the uninitialized collection to be + // loaded from the DB. } - else { + else if ( action.performOnLazyProperty() ) { + // The (non-collection) attribute needs to be initialized so that + // the action can be performed on the initialized attribute. LazyAttributeLoadingInterceptor interceptor = persister.getInstrumentationMetadata().extractInterceptor( parent ); child = interceptor.fetchAttribute( parent, propertyName ); } + else { + // Nothing to do, so just skip cascading to this lazy (non-collection) attribute. + continue; + } } else { child = persister.getPropertyValue( parent, i );