Reputation: 2673
In my GWT application, I pass an Object to the server for persistence with Hibernate. This Object contains a list of another object. Each element in the list contains a Map which is another Hibernate table.
In order to do this transaction, it is my understanding that I must first:
Here is some quick code on what I'm doing:
public void saveOrUpdateObject(final Foo foo)
{
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Object lookup = myDAO.getObject(foo.getUniqueValue());
if (lookup != null) {
lookup.getList().clear();
lookup.addAll(foo.getList());
myDAO.update(lookup);
}
else {
myDAO.save(foo);
}
}
Using this method, I occasionally get a HibernateException:
org.hibernate.HibernateException: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: my.Foo.list
What is the proper way to update an Object that contains a collection using Hibernate?
Upvotes: 2
Views: 6497
Reputation: 1642
The problem has to do with having both managed and unmanaged objects:
When you call lookup.getList().clear()
, you are signalling to Hibernate that everything in that managed list needs to be deleted (due to the all-delete-orphan
cascading). However, you then come back and add a bunch of stuff to that (managed) list, including some things that were probably already there. Hibernate gets confused and throws an Exception.
Instead of manually tweaking the managed object's list, use merge(foo)
to update the persistent instance's state with the unmanaged instance. From the Hibernate manual:
if there is a persistent instance with the same identifier currently associated with the session, copy the state of the given object onto the persistent instance
Merging puts the responsibility of figuring out which state is updated onto Hibernate.
Upvotes: 5