JPA CascadeType.ALL nie usuwa sierot


132

Mam problem z usunięciem węzłów osieroconych przy użyciu JPA z następującym mapowaniem

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

Mam problem z osieroconymi rolami kręcącymi się po bazie danych.

Mogę użyć adnotacji org.hibernate.annotations.Cascade specyficznej dla Hibernate tag, ale oczywiście nie chcę wiązać mojego rozwiązania z implementacją Hibernate.

EDYCJA : Wygląda na to, że JPA 2.0 będzie to obsługiwać.

Odpowiedzi:


164

Jeśli używasz go z Hibernate, będziesz musiał jawnie zdefiniować adnotację CascadeType.DELETE_ORPHAN, której można używać w połączeniu z JPA CascadeType.ALL.

Jeśli nie planujesz używać Hibernacji, musisz najpierw jawnie usunąć elementy podrzędne, a następnie usunąć główny rekord, aby uniknąć jakichkolwiek osieroconych rekordów.

sekwencja wykonania

  1. pobierz główny wiersz do usunięcia
  2. pobierz elementy potomne
  3. usuń wszystkie elementy podrzędne
  4. usuń główny wiersz
  5. Zamknij sesję

W przypadku JPA 2.0 można teraz używać opcji orphanRemoval = true

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

3
dzięki Skończyło się na tym, że jechałem tą trasą, myślę, że to trochę przesadna specyfikacja JPA.
Paul Whelan,

13
Standard JPA 2.0 ma teraz deleteOrphan jako atrybut @OneToMany Jeśli używasz najnowszej hibernacji, możesz zrobić @OneToMany (..., deleteOrphan = true)
jomohke

jaka jest sekwencja wykonywania, gdy po prostu aktualizuję elementy podrzędne? czy dokumenty osierocone zostaną usunięte?
jAckOdE

113

Jeśli używasz JPA 2.0, możesz teraz używać orphanRemoval=trueatrybutu pliku@xxxToMany adnotacji, aby usunąć sieroty.

W rzeczywistości CascadeType.DELETE_ORPHANzostał wycofany w wersji 3.5.2-Final.


6
Właściwie uważam, że orphanRemoval = true oznacza coś innego, tj. Usunięcie obiektu, gdy usuwam go z kolekcji jego rodzica. Zobacz download.oracle.com/javaee/6/tutorial/doc/bnbqa.html#giqxy
Archie

Proszę przejść przez link Archiego.
Jigar Shah,

4
orphanRemoval = true też nie działa. Trzeba to zrobić w stary sposób.
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
Co się stanie, jeśli mam cascade = CascadeType.ALL, orphanRemoval = falsei usunę rodzica? Czy usunie dzieci, mimo że wyraźnie zabroniłem?
izogfif


7

możesz użyć @PrivateOwned, aby usunąć sieroty, np

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

5
Dzięki @reshma, należy zauważyć, że @PrivateOwned to rozszerzenie JPA eclipselink.
Paul Whelan,

5

Po prostu znajduję to rozwiązanie, ale w moim przypadku nie działa:

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

orphanRemoval = true nie ma żadnego efektu.


1
Musiałem wyczyścić i zbudować, zanim zmiana weszła w życie.
maralbjo

Wow, od godziny zastanawiałem się, dlaczego dodanie CascadeType.ALL na moim ManyToOne nie było kaskadowym usuwaniem. Oczyszczone, zbudowane i działa. Dzięki @maralbjo.
Andrew Mairose


2

Miałem ten sam problem i zastanawiałem się, dlaczego ten warunek poniżej nie usuwa sierot. Lista potraw nie została usunięta w Hibernate (5.0.3.Final), kiedy wykonałem nazwane zapytanie o usunięcie:

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

Wtedy przypomniałem sobie, że nie wolno mi używać nazwanego zapytania usuwającego , ale EntityManager. Ponieważ użyłem tej EntityManager.find(...)metody, aby pobrać jednostkę, a następnie EntityManager.remove(...)ją usunąć, naczynia również zostały usunięte.


2

Właśnie @OneToMany(cascade = CascadeType.ALL, mappedBy = "xxx", fetch = FetchType.LAZY, orphanRemoval = true) .

Usuń targetEntity = MyClass.class , działa świetnie.



0

Używałem mapowania jeden do jednego, ale dziecko nie było usuwane. JPA powodowało naruszenie klucza obcego

Po użyciu orphanRemoval = true problem został rozwiązany


@OneToOne (cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn (name = "CHILD_OID") private Child child;
vipin chauhan
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.