JPA 2.0/Hibernate и "orphanRemoval": просто замена объекта не удаляет старый

У меня есть вопрос относительно JPA 2.0, Hibernate и "orphanRemoval" .

Сначала моя настройка:

  • Spring 3.0.5.RELEASE
  • SprnigData JPA 1.0.1.RELEASE
  • Hibernate 3.5.2-Final
  • СУБД: PostgreSQL 9.0

У меня есть два довольно простых класса сущностей: "Пользователь" и "AvatarImage", "Пользователь" имеет "AvatarImage", и между "User" и "AvatarImage" есть отношение.

В классе "Пользователь" свойство выглядит следующим образом:

// class "User"
@OneToOne(cascade = CascadeType.ALL, fetch=FetchType.LAZY, orphanRemoval = true)
private AvatarImage    avatarImage;

Таким образом, если свойство "avatarImage" получает значение null, ссылка между "User" и "AvatarImage" удаляется, и механизм "orphanRemoval" удаляет "avatarImage" из базы данных (пожалуйста, исправьте меня, если я "Неправильно".

Поэтому, когда я обновляю "avatarImage" для определенного пользователя, мне в настоящее время нужно написать это:

user.setAvatarImage( null );  // First set it to null
userRepository.save( user );  // Now "orphanRemoval" will delete the old one

user.setAvatarImage( theNewAvatarImage );
userRepository.save( user );

Итак, сначала установите свойство "avatarImage" равным null, сохранив "user", а затем установите новый AvatarImage "theNewAvatarImage", снова сохраняя пользователя.

Это единственный способ, который в настоящее время работает для меня: "orphanRemoval" удалит старый "avatarImage" , установив его "null" , а затем сохранит пользователя.

Но я бы подумал, что этот код также должен работать:

user.setAvatarImage( theNewAvatarImage );
userRepository.save( user );

Поэтому я опускаю настройку "avatarImage" на "null" , но просто устанавливаю "theNewAvatarImage", заменяя старый "avatarImage" . Но это не сработает, старый AvatarImage не удаляется из базы данных при совершении транзакции.

Кто-нибудь знает, почему второй код (просто заменив AvatarImage, не устанавливая его до "null" до), не работает?

Я очень ценю любую помощь, которую вы можете предложить

Спасибо большое!

Ответы

Ответ 1

Это связано с билетами Hibernate JIRA HHH-5559 и HHH-6484. По большому счету, Hibernate на сегодняшний день требует, чтобы вы установили ссылку на null и сбросили контекст персистентности, прежде чем предоставлять новое значение для отношения (см. Тестовый пример в HHH-6484); только в таком случае Hibernate выдает инструкцию SQL DELETE, предоставляя сломанную реализацию (IMHO) для orphanRemoval.

Короче говоря, вам нужно будет дождаться исправления ошибок или написать код, чтобы свести на нет ссылки и сбросить контекст персистентности, или использовать поставщика JPA, который поддерживает orphanRemoval таким образом (EclipseLink 2.3.0 делает).

Ответ 2

По отношению к @OneToMany это связано с билетом Hibernate JIRA HHH-6709. Пожалуйста, проголосуйте за них, чтобы получить некоторое внимание.