HHH-6361: Patch ensuring that collection events have the correct stored
snapshot after merging a detached entity into the persistencecontext
This commit is contained in:
parent
5c562411e6
commit
7bb43baf0b
|
@ -264,6 +264,20 @@ public final class CollectionEntry implements Serializable {
|
|||
return snapshot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the stored snapshot for both the persistent collection and this collection entry.
|
||||
* Used during the merge of detached collections.
|
||||
*
|
||||
* @param collection the persistentcollection to be updated
|
||||
* @param storedSnapshot the new stored snapshot
|
||||
*/
|
||||
public void resetStoredSnapshot(PersistentCollection collection, Serializable storedSnapshot) {
|
||||
LOG.debugf("Reset storedSnapshot to %s for %s", storedSnapshot, this);
|
||||
|
||||
snapshot = storedSnapshot;
|
||||
collection.setSnapshot(loadedKey, role, snapshot);
|
||||
}
|
||||
|
||||
private void setLoadedPersister(CollectionPersister persister) {
|
||||
loadedPersister = persister;
|
||||
setRole( persister == null ? null : persister.getRole() );
|
||||
|
|
|
@ -29,9 +29,12 @@ import java.sql.ResultSet;
|
|||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.dom4j.Element;
|
||||
import org.dom4j.Node;
|
||||
|
@ -40,6 +43,7 @@ import org.hibernate.Hibernate;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.collection.spi.PersistentCollection;
|
||||
import org.hibernate.engine.spi.CollectionEntry;
|
||||
import org.hibernate.engine.spi.CollectionKey;
|
||||
import org.hibernate.engine.spi.EntityEntry;
|
||||
import org.hibernate.engine.spi.Mapping;
|
||||
|
@ -49,6 +53,7 @@ import org.hibernate.engine.spi.SessionImplementor;
|
|||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.MarkerObject;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.metamodel.relational.Size;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.collection.QueryableCollection;
|
||||
|
@ -512,12 +517,73 @@ public abstract class CollectionType extends AbstractType implements Association
|
|||
if ( ! ( ( PersistentCollection ) original ).isDirty() ) {
|
||||
( ( PersistentCollection ) result ).clearDirty();
|
||||
}
|
||||
|
||||
if (elemType instanceof AssociationType) {
|
||||
preserveSnapshot(( PersistentCollection )original, ( PersistentCollection ) result, (AssociationType) elemType, owner, copyCache, session);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void preserveSnapshot(PersistentCollection original ,PersistentCollection result, AssociationType elemType, Object owner,
|
||||
Map copyCache, SessionImplementor session) {
|
||||
Serializable originalSnapshot = original.getStoredSnapshot();
|
||||
Serializable resultSnapshot = result.getStoredSnapshot();
|
||||
Serializable targetSnapshot;
|
||||
|
||||
if (originalSnapshot instanceof List) {
|
||||
targetSnapshot = new ArrayList(((List) originalSnapshot).size());
|
||||
for (Object obj : (List) originalSnapshot) {
|
||||
((List) targetSnapshot).add(elemType.replace(obj, null, session, owner, copyCache));
|
||||
}
|
||||
|
||||
} else if (originalSnapshot instanceof Map) {
|
||||
if (originalSnapshot instanceof SortedMap) {
|
||||
targetSnapshot = new TreeMap(((SortedMap) originalSnapshot).comparator());
|
||||
} else {
|
||||
targetSnapshot = new HashMap(
|
||||
CollectionHelper.determineProperSizing( ((Map) originalSnapshot).size()),
|
||||
CollectionHelper.LOAD_FACTOR);
|
||||
}
|
||||
|
||||
for (Map.Entry<Object, Object> entry : ((Map<Object,Object>) originalSnapshot).entrySet()) {
|
||||
Object key = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
Object resultSnapshotValue = (resultSnapshot == null) ? null : ((Map<Object,Object>) resultSnapshot).get(key);
|
||||
|
||||
if (key == value) {
|
||||
Object newValue = elemType.replace(value, resultSnapshotValue, session, owner, copyCache );
|
||||
((Map) targetSnapshot).put(newValue, newValue);
|
||||
|
||||
} else {
|
||||
Object newValue = elemType.replace(value, resultSnapshotValue, session, owner, copyCache );
|
||||
((Map) targetSnapshot).put(key, newValue);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else if (originalSnapshot instanceof Object []) {
|
||||
Object [] arr = ( Object []) originalSnapshot;
|
||||
for (int i=0; i< arr.length; i++) {
|
||||
arr[i] = elemType.replace(arr[i], null, session, owner, copyCache );
|
||||
}
|
||||
targetSnapshot = originalSnapshot;
|
||||
|
||||
} else {
|
||||
// retain the same snapshot
|
||||
targetSnapshot = resultSnapshot;
|
||||
|
||||
}
|
||||
|
||||
CollectionEntry ce = session.getPersistenceContext().getCollectionEntry(result);
|
||||
if (ce != null) {
|
||||
ce.resetStoredSnapshot(result, targetSnapshot);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate a new "underlying" collection exhibiting the same capacity
|
||||
* charactersitcs and the passed "original".
|
||||
|
|
Loading…
Reference in New Issue