Skip to content

Commit

Permalink
HHH-6361: Patch ensuring that collection events have the correct stored
Browse files Browse the repository at this point in the history
snapshot after merging a detached entity into the persistencecontext
  • Loading branch information
Erik-Berndt Scheper authored and brmeyer committed Oct 29, 2012
1 parent 5c56241 commit 7bb43ba
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,20 @@ public Serializable getSnapshot() {
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() );
Expand Down Expand Up @@ -422,4 +436,4 @@ public static CollectionEntry deserialize(
( session == null ? null : session.getFactory() )
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,12 @@
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;
Expand All @@ -40,6 +43,7 @@
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;
Expand All @@ -49,6 +53,7 @@
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;
Expand Down Expand Up @@ -512,12 +517,73 @@ public Object replaceElements(
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".
Expand Down

0 comments on commit 7bb43ba

Please sign in to comment.