I am unsure about how to create a test case for this one. Reproduction steps:
Setup two entities with a bidirectional @OneToMany/@ManyToOne relationship like this:
@Entity
class Parent
{
@OneToMany(mappedBy="parent", cascade=CascadeType.ALL)
public List<Child> children;
}
@Entity
class Child
{
@ManyToOne
public Parent parent;
}
Create and persist a Parent with no children.
In a new session, load the Parent from the database.
Add a transient Child to the children collection.
Call a read operation like .size() on the children collection.
Attempt to persist the Parent
Exception will result
The ultimate issue:
When user does PersistentBag.add() under these circumstances write operation is queued.
PersistentBag.size() triggers PersistentBag.read() which triggers PersistentBag.initialize()
org.hibernate.engine.loading.CollectionLoadContext::endLoadingCollection() is eventually called. This is where the actual bug is.
endLoadingCollection() calls org.hibernate.collection.AbstractPersistentCollection::endRead() which flushes all queued operations.
AFTER flushing queued operations, endLoadingCollection() calls org.hibernate.enging.CollectionEntry::postInitialize() which creates what is supposed to be the pre-write snapshot of the bag.
Bag snapshot is now incorrect – it contains all entities queued for write. If any of these entities are transient, they will cause an exception in org.hibernate.collection.AbstractPersistentCollection.getOrpahans(). When it iterates over the old snapshot, it makes a call to org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved() that cannot handle transient entities. Normally this wouldn't be an issue, but because snapshot contains queued writes, it can contain transient entities.
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira