HHH-18842 CollectionType.replace() breaks if target is PersistentCollection, but not instance of Collection
This commit is contained in:
parent
2ba2695264
commit
6880f73ae0
|
@ -7,6 +7,7 @@ package org.hibernate.collection.spi;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
@ -92,6 +93,9 @@ public class PersistentArrayHolder<E> extends AbstractPersistentCollection<E> {
|
||||||
public Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException {
|
public Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException {
|
||||||
final Object[] sn = (Object[]) snapshot;
|
final Object[] sn = (Object[]) snapshot;
|
||||||
final Object[] arr = (Object[]) array;
|
final Object[] arr = (Object[]) array;
|
||||||
|
if ( arr.length == 0 ) {
|
||||||
|
return Arrays.asList( sn );
|
||||||
|
}
|
||||||
final ArrayList result = new ArrayList();
|
final ArrayList result = new ArrayList();
|
||||||
Collections.addAll( result, sn );
|
Collections.addAll( result, sn );
|
||||||
for ( int i=0; i<sn.length; i++ ) {
|
for ( int i=0; i<sn.length; i++ ) {
|
||||||
|
|
|
@ -601,10 +601,20 @@ public final class Cascade {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// a newly instantiated collection can't have orphans
|
||||||
|
final PersistentCollection<?> persistentCollection;
|
||||||
|
if ( child instanceof PersistentCollection<?> pc ) {
|
||||||
|
persistentCollection = pc;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
persistentCollection = eventSource.getPersistenceContext()
|
||||||
|
.getCollectionHolder( child );
|
||||||
|
}
|
||||||
|
|
||||||
final boolean deleteOrphans = style.hasOrphanDelete()
|
final boolean deleteOrphans = style.hasOrphanDelete()
|
||||||
&& action.deleteOrphans()
|
&& action.deleteOrphans()
|
||||||
&& elemType instanceof EntityType
|
&& elemType instanceof EntityType
|
||||||
&& child instanceof PersistentCollection<?> persistentCollection
|
&& persistentCollection != null
|
||||||
// a newly instantiated collection can't have orphans
|
// a newly instantiated collection can't have orphans
|
||||||
&& !persistentCollection.isNewlyInstantiated();
|
&& !persistentCollection.isNewlyInstantiated();
|
||||||
|
|
||||||
|
@ -617,7 +627,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( eventSource, entityName, (PersistentCollection<?>) child );
|
deleteOrphans( eventSource, entityName, persistentCollection );
|
||||||
|
|
||||||
if ( traceEnabled ) {
|
if ( traceEnabled ) {
|
||||||
LOG.tracev( "Done deleting orphans for collection: {0}", collectionType.getRole() );
|
LOG.tracev( "Done deleting orphans for collection: {0}", collectionType.getRole() );
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.hibernate.Incubating;
|
||||||
import org.hibernate.Internal;
|
import org.hibernate.Internal;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.collection.spi.AbstractPersistentCollection;
|
import org.hibernate.collection.spi.AbstractPersistentCollection;
|
||||||
|
import org.hibernate.collection.spi.PersistentArrayHolder;
|
||||||
import org.hibernate.collection.spi.PersistentCollection;
|
import org.hibernate.collection.spi.PersistentCollection;
|
||||||
import org.hibernate.engine.spi.CollectionEntry;
|
import org.hibernate.engine.spi.CollectionEntry;
|
||||||
import org.hibernate.engine.spi.CollectionKey;
|
import org.hibernate.engine.spi.CollectionKey;
|
||||||
|
@ -634,11 +635,31 @@ public abstract class CollectionType extends AbstractType implements Association
|
||||||
if ( target == null ) {
|
if ( target == null ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if ( target instanceof PersistentCollection ) {
|
if ( target instanceof Collection<?> collection ) {
|
||||||
final Collection collection = (Collection) target;
|
|
||||||
collection.clear();
|
collection.clear();
|
||||||
return collection;
|
return collection;
|
||||||
}
|
}
|
||||||
|
else if ( target instanceof Map<?,?> map ) {
|
||||||
|
map.clear();
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
final PersistenceContext persistenceContext = session.getPersistenceContext();
|
||||||
|
final PersistentCollection<?> collectionHolder = persistenceContext
|
||||||
|
.getCollectionHolder( target );
|
||||||
|
if ( collectionHolder != null ) {
|
||||||
|
if ( collectionHolder instanceof PersistentArrayHolder<?> persistentArrayHolder ) {
|
||||||
|
persistenceContext.removeCollectionHolder( target );
|
||||||
|
persistentArrayHolder.beginRead();
|
||||||
|
persistentArrayHolder.injectLoadedState( persistenceContext.getCollectionEntry( collectionHolder ).getLoadedPersister().getAttributeMapping(), null );
|
||||||
|
persistentArrayHolder.endRead();
|
||||||
|
persistentArrayHolder.dirty();
|
||||||
|
persistenceContext.addCollectionHolder( collectionHolder );
|
||||||
|
return persistentArrayHolder.getArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if ( !Hibernate.isInitialized( original ) ) {
|
if ( !Hibernate.isInitialized( original ) ) {
|
||||||
|
|
Loading…
Reference in New Issue