Skip to content

Commit afd2628

Browse files
beikovjrenaat
authored andcommitted
HHH-2862, HHH-1914 Make collection replacement a first class operation on PersistenceContext
1 parent a920bf1 commit afd2628

File tree

3 files changed

+48
-8
lines changed

3 files changed

+48
-8
lines changed

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

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,6 +1075,35 @@ public void addNewCollection(CollectionPersister persister, PersistentCollection
10751075
addCollection( collection, persister );
10761076
}
10771077

1078+
@Override
1079+
public void replaceCollection(CollectionPersister persister, PersistentCollection<?> oldCollection, PersistentCollection<?> collection) {
1080+
if ( !oldCollection.isDirectlyAccessible() ) {
1081+
throw new HibernateException(
1082+
"Replacement of not directly accessible collection found: " + oldCollection.getRole() );
1083+
}
1084+
assert !collection.isDirectlyAccessible();
1085+
final IdentityMap<PersistentCollection<?>, CollectionEntry> collectionEntries = getOrInitializeCollectionEntries();
1086+
final CollectionEntry oldEntry = collectionEntries.remove( oldCollection );
1087+
final CollectionEntry entry;
1088+
if ( oldEntry.getLoadedPersister() != null ) {
1089+
// This is an already existing/loaded collection so ensure the loadedPersister is initialized
1090+
entry = new CollectionEntry( collection, session.getFactory() );
1091+
}
1092+
else {
1093+
// A newly wrapped collection
1094+
entry = new CollectionEntry( persister, collection );
1095+
}
1096+
collectionEntries.put( collection, entry );
1097+
final Object key = collection.getKey();
1098+
if ( key != null ) {
1099+
final CollectionKey collectionKey = new CollectionKey( entry.getLoadedPersister(), key );
1100+
final PersistentCollection<?> old = addCollectionByKey( collectionKey, collection );
1101+
if ( old == null ) {
1102+
throw new HibernateException( "No collection for replacement found: " + collectionKey.getRole() );
1103+
}
1104+
}
1105+
}
1106+
10781107
/**
10791108
* Add a collection to the cache, with a given collection entry.
10801109
*

hibernate-core/src/main/java/org/hibernate/engine/spi/PersistenceContext.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
import org.checkerframework.checker.nullness.qual.Nullable;
2727

28+
2829
/**
2930
* Represents the state of "stuff" Hibernate is tracking, including (not exhaustive):
3031
* <ul>
@@ -408,6 +409,15 @@ void addInitializedDetachedCollection(
408409
CollectionPersister collectionPersister,
409410
PersistentCollection<?> collection);
410411

412+
/**
413+
* Replaces a directly accessible collection with the given one
414+
*
415+
* @param oldCollection
416+
* @param collection The collection to be associated with the persistence context
417+
* @since 7.0
418+
*/
419+
void replaceCollection(CollectionPersister persister, PersistentCollection<?> oldCollection, PersistentCollection<?> collection);
420+
411421
/**
412422
* add a collection we just pulled out of the cache (does not need initializing)
413423
*/

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

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -661,18 +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() ) {
664+
if ( target instanceof PersistentCollection<?> oldCollection
665+
&& oldCollection.isDirectlyAccessible() ) {
666666
// When a replace/merge is requested and the underlying collection is directly accessible,
667667
// use a new persistent collection, to avoid potential issues
668668
// like the underlying collection being unmodifiable and hence failing the element replacement
669669
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;
670+
final Object key = oldCollection.getKey();
671+
final PersistentCollection<?> newCollection = instantiate( session, collectionPersister, key );
672+
newCollection.initializeEmptyCollection( collectionPersister );
673+
newCollection.setSnapshot( key, oldCollection.getRole(), oldCollection.getStoredSnapshot() );
674+
session.getPersistenceContextInternal()
675+
.replaceCollection( collectionPersister, oldCollection, newCollection );
676+
target = newCollection;
676677
}
677678
//TODO: this is a little inefficient, don't need to do a whole
678679
// deep replaceElements() call

0 commit comments

Comments
 (0)