Нарушение спящего режима с помощью orphanRemoval

У меня проблемы с установкой JPA / Hibernate (3.5.3), где у меня есть объект, class «Учетная запись», в котором есть список дочерних объектов, «Контакт». Я пытаюсь добавить / удалить экземпляры контакта в список свойства учетной записи.

Добавление нового экземпляра в набор и вызов saveOrUpdate (account) сохраняют все прекрасное. Если я затем выберу контакт из списка и снова вызову saveOrUpdate, похоже, создается hibernate SQL, связанный с установкой для столбца account_id значения null, что нарушает ограничение базы данных.

Что я делаю не так?

Кодекс ниже явно упрощенная реферат, но я думаю, что она охватывает проблему, поскольку я вижу те же результаты в другом коде, который действительно об этом прост.

SQL:

CREATE TABLE account ( INT account_id ); CREATE TABLE contact ( INT contact_id, INT account_id REFERENCES account (account_id) ); 

Ява:

 @Entity class Account { @Id @Column public Long id; @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn(name = "account_id") public List contacts; } @Entity class Contact { @Id @Column public Long id; @ManyToOne(optional = false) @JoinColumn(name = "account_id", nullable = false) public Account account; } Account account = new Account(); Contact contact = new Contact(); account.contacts.add(contact); saveOrUpdate(account); // some time later, like another servlet request.... account.contacts.remove(contact); saveOrUpdate(account); 

Результат:

 UPDATE contact SET account_id = null WHERE contact_id = ? 

Редактировать # 1:

Возможно, это на самом деле ошибка http://opensource.atlassian.com/projects/hibernate/browse/HHH-5091

Редактировать # 2:

У меня есть решение, которое, похоже, работает, но предполагает использование Hibernate API

 class Account { @SuppressWarnings("deprecation") @OneToMany(cascade = CascadeType.ALL, mappedBy = "account") @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN) @JoinColumn(name = "account_id", nullable = false) private Set contacts = new HashSet(); } class Contact { @ManyToOne(optional = false) @JoinColumn(name = "account_id", nullable = false) private Account account; } 

Поскольку Hibernate CascadeType.DELETE_ORPHAN устарел, я должен предположить, что он был заменен версией JPA2, но в реализации чего-то не хватает.

Некоторые замечания:

  • Поскольку у вас есть двунаправленная связь, вам нужно добавить атрибут mappedBy чтобы объявить свою сторону ассоциации.
  • Также не забывайте, что вам нужно управлять обеими сторонами ссылки при работе с двунаправленными ассоциациями, и я предлагаю использовать для этого защитные методы (показано ниже).
  • И вы должны реализовать equals и hashCode on Contact .

Итак, в Account измените отображение следующим образом:

 @Entity public class Account { @Id @GeneratedValue public Long id; @OneToMany(cascade = CascadeType.ALL, mappedBy = "account", orphanRemoval = true) public List contacts = new ArrayList(); public void addToContacts(Contact contact) { this.contacts.add(contact); contact.setAccount(this); } public void removeFromContacts(Contact contact) { this.contacts.remove(contact); contact.setAccount(null); } // getters, setters } 

В Contact важная часть состоит в том, что поле @ManyToOne должно иметь optional флаг, установленный в false :

 @Entity public class Contact { @Id @GeneratedValue public Long id; @ManyToOne(optional = false) public Account account; // getters, setters, equals, hashCode } 

С этими изменениями выполняются только следующие работы:

 Account account = new Account(); Contact contact = new Contact(); account.addToContact(contact); em.persist(account); em.flush(); assertNotNull(account.getId()); assertNotNull(account.getContacts().get(0).getId()); assertEquals(1, account.getContacts().size()); account.removeFromContact(contact); em.merge(account); em.flush(); assertEquals(0, account.getContacts().size()); 

И потерянный Contact удаляется, как и ожидалось. Протестировано с Hibernate 3.5.3-Final.

  • Бесконечная recursion с выпуском Jackson JSON и Hibernate JPA
  • Postgresql UUID поддерживается Hibernate?
  • JPA - сохранение отношения от одного до большого
  • Должен ли я преобразовывать объекты Entity (Persistent) в объекты DTO?
  • Hibernate / JPA - аннотирование методов бобов и полей
  • org.hibernate.MappingException: Не удалось определить тип для: java.util.List, at table: College, для столбцов:
  • В чем разница между JPA и Hibernate?
  • @Basic (необязательно = false) vs @Column (nullable = false) в JPA
  • Когда Hibernate сбрасывает сеанс, как он решает, какие объекты в сеансе загрязнены?
  • Любые хорошие инструменты ORM для разработки Android?
  • Hibernate, iBatis, Java EE или другой инструмент Java ORM
  • Давайте будем гением компьютера.