Обновление объекта, содержащего список в Hibernate - PullRequest
2 голосов
/ 23 сентября 2011

В моем приложении GWT я передаю объект на сервер для сохранения в Hibernate. Этот объект содержит список другого объекта. Каждый элемент в списке содержит карту, которая является другой таблицей Hibernate.

Чтобы выполнить эту транзакцию, я понимаю, что должен сначала:

  1. Выполните поиск, чтобы получить постоянный объект из базы данных через Hibernate
  2. Изменить объект
  3. Обновление объекта через Hibernate

Вот небольшой код того, что я делаю:

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);
   }
}

Используя этот метод, я иногда получаю HibernateException:

org.hibernate.HibernateException: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: my.Foo.list

Как правильно обновить объект, содержащий коллекцию, с помощью Hibernate?

1 Ответ

5 голосов
/ 23 сентября 2011

Проблема связана с наличием как управляемых, так и неуправляемых объектов:

  • lookup - это управляемый объект, как и lookup.list и все, что в нем
  • foo не является управляемым объектом, как и ничего в foo.list

Когда вы звоните lookup.getList().clear(), вы сигнализируете Hibernate, что все в этом управляемом списке необходимо удалить (из-за каскада all-delete-orphan). Однако вы затем возвращаетесь и добавляете в этот (управляемый) список кучу вещей, включая некоторые вещи, которые, вероятно, уже были там. Hibernate запутывается и выдает исключение.

Вместо ручной настройки списка управляемых объектов используйте merge(foo), чтобы обновить состояние постоянного экземпляра с помощью неуправляемого экземпляра. Из руководства пользователя Hibernate :

если существует постоянный экземпляр с тем же идентификатором, который в настоящее время связан с сеансом, скопируйте состояние данного объекта в постоянный экземпляр

При слиянии выясняется, какое состояние обновляется в Hibernate.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...