HHH-13129 : Cascaded merge fails for detached bytecode-enhanced entity with uninitialized ToOne
This commit is contained in:
parent
c62f0a75cd
commit
a66ca0463e
|
@ -12,12 +12,10 @@ import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
|
|
||||||
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
|
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
|
||||||
import org.hibernate.collection.spi.PersistentCollection;
|
import org.hibernate.collection.spi.PersistentCollection;
|
||||||
import org.hibernate.engine.spi.CascadeStyle;
|
import org.hibernate.engine.spi.CascadeStyle;
|
||||||
import org.hibernate.engine.spi.CascadingAction;
|
import org.hibernate.engine.spi.CascadingAction;
|
||||||
import org.hibernate.engine.spi.CascadingActions;
|
|
||||||
import org.hibernate.engine.spi.CollectionEntry;
|
import org.hibernate.engine.spi.CollectionEntry;
|
||||||
import org.hibernate.engine.spi.EntityEntry;
|
import org.hibernate.engine.spi.EntityEntry;
|
||||||
import org.hibernate.engine.spi.Status;
|
import org.hibernate.engine.spi.Status;
|
||||||
|
@ -102,25 +100,46 @@ public final class Cascade {
|
||||||
final Object child;
|
final Object child;
|
||||||
if ( isUninitializedProperty ) {
|
if ( isUninitializedProperty ) {
|
||||||
// parent is a bytecode enhanced entity.
|
// parent is a bytecode enhanced entity.
|
||||||
// cascading to an uninitialized, lazy value.
|
// Cascade to an uninitialized, lazy value only if
|
||||||
if ( types[ i ].isCollectionType() ) {
|
// parent is managed in the PersistenceContext.
|
||||||
// The collection does not need to be loaded from the DB.
|
// If parent is a detached entity being merged,
|
||||||
// CollectionType#resolve will return an uninitialized PersistentCollection.
|
// then parent will not be in the PersistencContext
|
||||||
// The action will initialize the collection later, if necessary.
|
// (so lazy attributes must not be initialized).
|
||||||
child = types[ i ].resolve( LazyPropertyInitializer.UNFETCHED_PROPERTY, eventSource, parent );
|
if ( eventSource.getPersistenceContext().getEntry( parent ) == null ) {
|
||||||
// TODO: it would be nice to be able to set the attribute in parent using
|
// parent was not in the PersistenceContext
|
||||||
// persister.setPropertyValue( parent, i, child ).
|
continue;
|
||||||
// Unfortunately, that would cause the uninitialized collection to be
|
|
||||||
// loaded from the DB.
|
|
||||||
}
|
}
|
||||||
else if ( action.performOnLazyProperty() ) {
|
if ( types[ i ].isCollectionType() ) {
|
||||||
// The (non-collection) attribute needs to be initialized so that
|
// CollectionType#getCollection gets the PersistentCollection
|
||||||
// the action can be performed on the initialized attribute.
|
// that corresponds to the uninitialized collection from the
|
||||||
LazyAttributeLoadingInterceptor interceptor = persister.getInstrumentationMetadata().extractInterceptor( parent );
|
// PersistenceContext. If not present, an uninitialized
|
||||||
|
// PersistentCollection will be added to the PersistenceContext.
|
||||||
|
// The action may initialize it later, if necessary.
|
||||||
|
// This needs to be done even when action.performOnLazyProperty() returns false.
|
||||||
|
final CollectionType collectionType = (CollectionType) types[i];
|
||||||
|
child = collectionType.getCollection(
|
||||||
|
collectionType.getKeyOfOwner( parent, eventSource ),
|
||||||
|
eventSource,
|
||||||
|
parent,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if ( types[ i ].isComponentType() ) {
|
||||||
|
// Hibernate does not support lazy embeddables, so this shouldn't happen.
|
||||||
|
throw new UnsupportedOperationException(
|
||||||
|
"Lazy components are not supported."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if ( action.performOnLazyProperty() && types[ i ].isEntityType() ) {
|
||||||
|
// Only need to initialize a lazy entity attribute when action.performOnLazyProperty()
|
||||||
|
// returns true.
|
||||||
|
LazyAttributeLoadingInterceptor interceptor = persister.getInstrumentationMetadata()
|
||||||
|
.extractInterceptor( parent );
|
||||||
child = interceptor.fetchAttribute( parent, propertyName );
|
child = interceptor.fetchAttribute( parent, propertyName );
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Nothing to do, so just skip cascading to this lazy (non-collection) attribute.
|
// Nothing to do, so just skip cascading to this lazy attribute.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,6 +131,7 @@ public class DefaultDeleteEventListener implements DeleteEventListener, Callback
|
||||||
persister,
|
persister,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
persister.afterReassociate( entity, source );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LOG.trace( "Deleting a persistent instance" );
|
LOG.trace( "Deleting a persistent instance" );
|
||||||
|
|
Loading…
Reference in New Issue