Skip to content

Commit 9b0b482

Browse files
committed
HHH-1914 Fix merge support for unmodifiable collections
1 parent f480369 commit 9b0b482

File tree

3 files changed

+14
-3
lines changed

3 files changed

+14
-3
lines changed

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,19 @@ private Object replaceOriginal(
661661
final boolean wasClean =
662662
target instanceof PersistentCollection<?> collection
663663
&& !collection.isDirty();
664+
if ( target instanceof PersistentCollection<?> existingPersistentCollection
665+
&& existingPersistentCollection.isDirectlyAccessible() ) {
666+
// When a replace/merge is requested and the underlying collection is directly accessible,
667+
// use a new persistent collection, to avoid potential issues
668+
// like the underlying collection being unmodifiable and hence failing the element replacement
669+
final CollectionPersister collectionPersister = getPersister( session );
670+
final Object key = existingPersistentCollection.getKey();
671+
final PersistentCollection<?> persistentCollection = instantiate( session, collectionPersister, key );
672+
persistentCollection.initializeEmptyCollection( collectionPersister );
673+
persistentCollection.setSnapshot( key, existingPersistentCollection.getRole(), existingPersistentCollection.getStoredSnapshot() );
674+
session.getPersistenceContextInternal().addInitializedDetachedCollection( collectionPersister, persistentCollection );
675+
target = persistentCollection;
676+
}
664677
//TODO: this is a little inefficient, don't need to do a whole
665678
// deep replaceElements() call
666679
replaceElements( result, target, owner, copyCache, session );

hibernate-core/src/test/java/org/hibernate/orm/test/annotations/manytomany/UnmodifiableCollectionMergeTest.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import java.util.Set;
1010

1111
import org.hibernate.dialect.H2Dialect;
12-
import org.hibernate.testing.orm.junit.FailureExpected;
1312
import org.hibernate.testing.orm.junit.RequiresDialect;
1413
import org.hibernate.testing.orm.junit.DomainModel;
1514
import org.hibernate.testing.orm.junit.SessionFactory;
@@ -21,7 +20,6 @@
2120
* @author Jan Schatteman
2221
*/
2322
@RequiresDialect( value = H2Dialect.class )
24-
@FailureExpected( jiraKey = "HHH-1914", reason = "throws an UnsupportedOperationException")
2523
@DomainModel(
2624
annotatedClasses = {
2725
Cat.class, Woman.class, Man.class

hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,7 @@ public void testMergeManaged(SessionFactoryScope scope) {
623623
session.getTransaction().commit();
624624

625625
assertInsertCount( 1, scope );
626-
assertUpdateCount( 0, scope );
626+
assertUpdateCount( 1, scope );
627627

628628
assertThat( root.getChildren().size(), is( 1 ) );
629629
assertTrue( root.getChildren().contains( mergedChild ) );

0 commit comments

Comments
 (0)