Каскадное обновление / удаление JPA 2.0

У меня есть отношение nn, сопоставленное с этими 3 объектами:

@Entity
public class ApplicatifDo {
   .....
   @OneToMany(cascade = CascadeType.ALL, mappedBy = "applicatifDo", fetch = FetchType.EAGER, orphanRemoval = true)
   private Set<ApplicatifTerminalDo> applicatifTerminalSet;
   .....
}

@Entity
public class ApplicatifTerminalDo {
   ......
   @ManyToOne
   @JoinColumn(name = "idApplicatif", nullable = false)
   private ApplicatifDo applicatifDo;
   @ManyToOne
   @JoinColumn(name = "idTerminal", nullable = false)
   private TerminalDo terminalDo;

   @Column
   private String remarques;
   ......
}

@Entity
public class TerminalDo {
   ......
   @OneToMany(cascade = CascadeType.ALL, mappedBy = "terminalDo", fetch = FetchType.EAGER, orphanRemoval = true)
   private Set<ApplicatifTerminalDo> applicatifTerminalSet;
   ......
}

Я пытаюсь выполнить тест, в котором у меня есть сохраненный ApplicatifDo, в котором содержится множество ApplicatifTerminalDo в своем наборе, и я изменяю некоторые из них, удаляю другие, добавляю новые в этом наборе:

modifyRemarques(firstElement(applicatifDo.getApplicatifTerminalSet()));
applicatifDo.getApplicatifTerminalSet.add(anotherApplicatifTerminal);
applicatifDo.getApplicatifTerminalSet.remove(onceApplicatifTerminal);

Затем, когда я объединяю это в моей БД, в моей соединительной таблице ApplicatifTerminal я вижу изменение "Remarques", а также новые сущности ApplicatifTerminal, но удаление не работает, и сущности, которые должны быть удалены, все еще присутствует в моей таблице соединений (и я использую orphanRemoval).

И я не получаю ошибку в консоли, когда я тестирую это, но все же объекты удаления больше не должны быть в БД.

PS: я использовал один и тот же метод для отношения 1-n, и каскадирование всех типов изменений в содержавшемся множестве сущностей в родительской сущности работало хорошо (включая удаление).

Обновить:

Я пытался удалить OnceApplicatifTerminal из TerminalDo, как сказал Крис, но все равно не работает. Вот код:

            Iterator<ApplicatifTerminalDo> iterator = applicatifDo
                .getApplicatifTerminalSet().iterator();
            boolean first = true;
            while (iterator.hasNext()) {
                ApplicatifTerminalDo element = iterator.next();
                if (!first) {
                    element.setRemarques("remarques updated");
                } else {
                    iterator.remove();
                    element.getTerminalDo().setApplicatifTerminalSet(
                            applicatifDo.getApplicatifTerminalSet());
                    first = false;
                }
            }

Здесь я пытаюсь удалить первый ApplicatifTerminalDo из списка и обновить значение столбца для других. И когда я объединяюсь, значения меняются, но удаление не работает, даже если я получаю TerminalDo для удаления, поместите обновленный Набор ApplicatfTerminal.

Можно ли добиться того, что я хочу сделать? Как лучше всего обновлять / удалять строки из таблицы соединений, созданной лично?

Пожалуйста, помогите, я не понимаю почему.

1 ответ

Решение

Вы ожидаете, что удаление сирот вступит в силу, потому что вы разыменовали OnceApplicatifTerminal, и хотите OnceApplicatifTerminal.

Удаление сирот имеет свои недостатки, на которые намекают, когда оно называется частной собственностью в других ORM: объект действительно должен принадлежать только частному лицу, что здесь не так. Вы сталкиваетесь с проблемами, когда вы звоните applicatifDo.getApplicatifTerminalSet.remove(onceApplicatifTerminal); потому что существует экземпляр TerminalDo, который также ссылается на этот экземпляр OnceApplicatifTerminal. В JPA разрешено использование кэширования, поэтому, если этот TerminalDo-> OnceApplicatifTerminal также не будет очищен в ваших сущностях, он останется со ссылкой на сущность OnceApplicatifTerminal, и из-за ваших настроек каскадирования Persist/Merge это приведет к его воскрешению, Просто удалив настройки каскада в TerminalDo->ApplicatifTerminalDo, как будто ссылка не удалена, кэш все равно останется со ссылкой на эту несуществующую сущность.

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

Другие вопросы по тегам