JPA CascadeType.ALL не видаляє сиріт


132

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

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

У мене виникає проблема осиротілих ролей, що звисають навколо бази даних.

Я можу використовувати org.hibernate.annotations.Cascadeспецифічний тег аннотації до сну, але я очевидно, що я не хочу прив'язувати своє рішення до режиму сну.

EDIT : Схоже, 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
Арчі

Будь ласка, перейдіть за посиланням Арчі.
Jigar Shah

4
orphanRemoval = true також не працює. Це потрібно зробити по-старому.
Джо Алмор

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


7

ви можете використовувати @PrivateOwned для видалення сиріт, наприклад

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

5
Спасибі @reshma, слід зазначити, @PrivateOwned - це розширення JPA для eclipselink.
Пол Уїлан

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 (ім'я = "CHILD_OID") приватна дитина-дитина;
vipin chauhan
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.