Skip to content

Commit 3dfb973

Browse files
committed
HHH-18842 CollectionType.replace() breaks if target is PersistentCollection, but not instance of Collection
1 parent e094b3c commit 3dfb973

File tree

3 files changed

+47
-7
lines changed

3 files changed

+47
-7
lines changed

hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentArrayHolder.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.io.Serializable;
1010
import java.lang.reflect.Array;
1111
import java.util.ArrayList;
12+
import java.util.Arrays;
1213
import java.util.Collection;
1314
import java.util.Collections;
1415
import java.util.Iterator;
@@ -94,6 +95,9 @@ public boolean isSnapshotEmpty(Serializable snapshot) {
9495
public Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException {
9596
final Object[] sn = (Object[]) snapshot;
9697
final Object[] arr = (Object[]) array;
98+
if ( arr.length == 0 ) {
99+
return Arrays.asList( sn );
100+
}
97101
final ArrayList result = new ArrayList();
98102
Collections.addAll( result, sn );
99103
for ( int i=0; i<sn.length; i++ ) {

hibernate-core/src/main/java/org/hibernate/engine/internal/Cascade.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -621,12 +621,22 @@ private static <T> void cascadeCollectionElements(
621621
}
622622
}
623623

624+
// a newly instantiated collection can't have orphans
625+
final PersistentCollection<?> persistentCollection;
626+
if ( child instanceof PersistentCollection<?> ) {
627+
persistentCollection = (PersistentCollection<?>) child;
628+
}
629+
else {
630+
persistentCollection = eventSource.getPersistenceContext()
631+
.getCollectionHolder( child );
632+
}
633+
624634
final boolean deleteOrphans = style.hasOrphanDelete()
625635
&& action.deleteOrphans()
626636
&& elemType instanceof EntityType
627-
&& child instanceof PersistentCollection
637+
&& persistentCollection != null
628638
// a newly instantiated collection can't have orphans
629-
&& ! ( (PersistentCollection<?>) child ).isNewlyInstantiated();
639+
&& !persistentCollection.isNewlyInstantiated();
630640

631641
if ( deleteOrphans ) {
632642
final boolean traceEnabled = LOG.isTraceEnabled();
@@ -637,7 +647,7 @@ private static <T> void cascadeCollectionElements(
637647
// 1. newly instantiated collections
638648
// 2. arrays (we can't track orphans for detached arrays)
639649
final String entityName = collectionType.getAssociatedEntityName( eventSource.getFactory() );
640-
deleteOrphans( eventSource, entityName, (PersistentCollection<?>) child );
650+
deleteOrphans( eventSource, entityName, persistentCollection );
641651

642652
if ( traceEnabled ) {
643653
LOG.tracev( "Done deleting orphans for collection: {0}", collectionType.getRole() );

hibernate-core/src/main/java/org/hibernate/type/CollectionType.java

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.hibernate.Internal;
2626
import org.hibernate.MappingException;
2727
import org.hibernate.collection.spi.AbstractPersistentCollection;
28+
import org.hibernate.collection.spi.PersistentArrayHolder;
2829
import org.hibernate.collection.spi.PersistentCollection;
2930
import org.hibernate.engine.spi.CollectionEntry;
3031
import org.hibernate.engine.spi.CollectionKey;
@@ -641,11 +642,36 @@ public Object replace(
641642
if ( target == null ) {
642643
return null;
643644
}
644-
if ( target instanceof PersistentCollection ) {
645-
final Collection collection = (Collection) target;
646-
collection.clear();
647-
return collection;
645+
if ( target instanceof Collection<?> ) {
646+
( (Collection<?>) target ).clear();
647+
return target;
648648
}
649+
else if ( target instanceof Map<?, ?> ) {
650+
( (Map<?, ?>) target ).clear();
651+
return target;
652+
}
653+
else {
654+
final PersistenceContext persistenceContext = session.getPersistenceContext();
655+
final PersistentCollection<?> collectionHolder = persistenceContext
656+
.getCollectionHolder( target );
657+
if ( collectionHolder != null ) {
658+
if ( collectionHolder instanceof PersistentArrayHolder<?> ) {
659+
PersistentArrayHolder<?> persistentArrayHolder = (PersistentArrayHolder<?>) collectionHolder;
660+
persistenceContext.removeCollectionHolder( target );
661+
persistentArrayHolder.beginRead();
662+
persistentArrayHolder.injectLoadedState(
663+
persistenceContext.getCollectionEntry( collectionHolder )
664+
.getLoadedPersister()
665+
.getAttributeMapping(), null
666+
);
667+
persistentArrayHolder.endRead();
668+
persistentArrayHolder.dirty();
669+
persistenceContext.addCollectionHolder( collectionHolder );
670+
return persistentArrayHolder.getArray();
671+
}
672+
}
673+
}
674+
649675
return null;
650676
}
651677
if ( !Hibernate.isInitialized( original ) ) {

0 commit comments

Comments
 (0)