JPA CascadeType.ALL не удаляет сирот


132

У меня возникают проблемы с удалением сиротских узлов с помощью JPA со следующим сопоставлением

@OneToMany (cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "owner")
private List<Bikes> bikes;

У меня проблема с потерянными ролями, висящими в базе данных.

Я могу использовать org.hibernate.annotations.Cascadeспециальный тег аннотации Hibernate, но, очевидно, я не хочу связывать свое решение с реализацией Hibernate.

РЕДАКТИРОВАТЬ : Кажется, JPA 2.0 будет поддерживать это.

Ответы:


164

Если вы используете его с Hibernate, вам придется явно определить аннотацию CascadeType.DELETE_ORPHAN, которую можно использовать вместе с JPA CascadeType.ALL.

Если вы не планируете использовать Hibernate, вам придется сначала явно удалить дочерние элементы, а затем удалить основную запись, чтобы избежать любых потерянных записей.

последовательность выполнения

  1. выбрать основную строку для удаления
  2. получить дочерние элементы
  3. удалить все дочерние элементы
  4. удалить основную строку
  5. закрытие сессии

В JPA 2.0 теперь вы можете использовать опцию orphanRemoval = true

@OneToMany(mappedBy="foo", orphanRemoval=true)

3
спасибо, что в итоге я пошел по этому пути, я думаю, что это немного перебор для спецификации JPA.
Пол Уилан

13
Стандарт JPA 2.0 теперь имеет deleteOrphan в качестве атрибута для @OneToMany. Если вы используете последнюю версию гибернации, вы можете использовать @OneToMany (..., deleteOrphan = true)
jomohke

что такое последовательность выполнения, когда я просто обновляю дочерние элементы? будут ли удалены записи-сироты?
jAckOdE

113

Если вы используете JPA 2.0, теперь вы можете использовать orphanRemoval=trueатрибут @xxxToManyаннотации для удаления сирот.

Фактически, CascadeType.DELETE_ORPHANустарел в 3.5.2-Final.


6
На самом деле я думаю, что orphanRemoval = true означает что-то еще, то есть удалить объект, когда я удаляю его из коллекции его родителя. См. Download.oracle.com/javaee/6/tutorial/doc/bnbqa.html#giqxy
Archie,

Пожалуйста, пройдите по ссылке Арчи.
Jigar Shah

4
orphanRemoval = true тоже не работает. Это нужно делать по старинке.
Joe Almore

45
╔═════════════╦═════════════════════╦═════════════════════╗
   Action      orphanRemoval=true    CascadeType.ALL   
╠═════════════╬═════════════════════╬═════════════════════╣
   delete         deletes parent      deletes parent   
   parent         and orphans         and orphans      
╠═════════════╬═════════════════════╬═════════════════════╣
   change                                              
  children      deletes orphans         nothing        
    list                                               
╚═════════════╩═════════════════════╩═════════════════════╝

1
Что произойдет, если я cascade = CascadeType.ALL, orphanRemoval = falseудалю родительский элемент? Удалит ли он детей, хотя я специально сказал НЕ делать этого?
izogfif 04


7

вы можете использовать @PrivateOwned для удаления сирот, например

@OneToMany(mappedBy = "masterData", cascade = {
        CascadeType.ALL })
@PrivateOwned
private List<Data> dataList;

5
Спасибо @reshma, следует отметить, что @PrivateOwned является расширением eclipselink JPA.
Пол Уилан

5

Я просто нашел это решение, но в моем случае оно не работает:

@OneToMany(cascade = CascadeType.ALL, targetEntity = MyClass.class, mappedBy = "xxx", fetch = FetchType.LAZY, orphanRemoval = true) 

orphanRemoval = true не действует.


1
Мне нужно было очистить и построить, прежде чем изменения вступили в силу.
maralbjo

Вау, я уже час искал, почему добавление CascadeType.ALL на моем ManyToOne не было каскадным удалением. Почистил и построил и все работает. Спасибо @maralbjo.
Эндрю Майроуз


2

У меня была та же проблема, и я задавался вопросом, почему это условие ниже не удаляет сирот. Список блюд не был удален в Hibernate (5.0.3.Final), когда я выполнил именованный запрос на удаление:

@OneToMany(mappedBy = "menuPlan", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Dish> dishes = new ArrayList<>();

Тогда я вспомнил, что я не должен использовать именованный запрос на удаление , но EntityManager. Поскольку я использовал EntityManager.find(...)метод для извлечения объекта, а затем EntityManager.remove(...)для его удаления, также были удалены блюда.


2

Просто @OneToMany(cascade = CascadeType.ALL, mappedBy = "xxx", fetch = FetchType.LAZY, orphanRemoval = true).

Удалите targetEntity = MyClass.class , он отлично работает.



0

Я использовал сопоставление один в один, но дочерний элемент не удалялся. JPA давал нарушение внешнего ключа.

После использования orphanRemoval = true проблема была решена


@OneToOne (cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn (name = "CHILD_OID") частный дочерний ребенок;
vipin chauhan
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.