I've found bugs related to collections that have been dereferenced by:
- setting a non-null reference to a collection in a managed entity to null;
- replacing a non-null collection with a different non-null collection in a managed entity;
- merging an entity with a null collection; in this case, the merged entity has a null reference to the collection, but a PersistentCollection is stored in the EntityEntry state (instead of null). On flush, that PersistentCollection will be dereferenced.
The bugs I've found so far:
1) The dereferenced AbstractPersistentCollection.session is not nullified. This is straightforward to fix.
2) If only the collection has changed and the collection owner is not versioned, EntityEntry.postUpdate() will not be called to update the EntityEntry state. This is because Hibernate does not consider a non-versioned entity "dirty" due to a change in the collection. (CollectionType.isDirty() returns false if isOwnerVersioned( session ) is false). Is there a safe place in the flush process to call EntityEntry.postUpdate() to update the loaded state? If not, a possible fix (that could affect performance) is to change CollectionType.isDirty() to not depend on whether the entity is versioned.
3) If a managed, versioned entity has an uninitialized collection and that collection reference is nullified, CollectionType.isDirty() will return false because of a bug in CollectionType.isEqual(). When a collection is uninitialized, it's wrapped collection is null. All the implementations of PersistentCollection.isWrapper(Object collection) compare the collection argument (which is null) to the wrapped collection in the uninitialized PersistentCollection (which is also null). In this case, CollectionType.isEqual( x, y ) will return true; as a result CollectionType.isDirty() will return false.