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.

Kango_V
источник
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;
Reshma
источник
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.
Эндрю Майроуз
4

Согласно Java Persistence with Hibernate , каскадное удаление сиротства недоступно в виде аннотации JPA.

Это также не поддерживается в JPA XML.

Инструментарий
источник
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 , он отлично работает.

Kohan95
источник
1

Для записей в OpenJPA до JPA2 это был @ElementDependant.

Симона Джанни
источник
0

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

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

Випин Чаухан
источник
@OneToOne (cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn (name = "CHILD_OID") частный дочерний ребенок;
vipin chauhan