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.