Jestem trochę zdezorientowany co do orphanRemoval
atrybutu JPA 2.0 .
Myślę, że widzę, że jest to potrzebne, gdy używam narzędzi do generowania DB mojego dostawcy JPA do stworzenia bazowego DDL bazy danych, aby mieć ON DELETE CASCADE
konkretną relację.
Jeśli jednak DB istnieje i ma już ON DELETE CASCADE
relację, czy to nie wystarczy, aby odpowiednio skasować usunięcie? Co robi orphanRemoval
dodatkowo?
Twoje zdrowie
źródło
Przykład wzięty tutaj :
Kiedy
Employee
obiekt encji jest usuwany, operacja usuwania jest kaskadowana z referencyjnymAddress
obiektem encji. Pod tym względemorphanRemoval=true
icascade=CascadeType.REMOVE
są identyczne, a jeśliorphanRemoval=true
jest określony,CascadeType.REMOVE
jest zbędny.Różnica między tymi dwoma ustawieniami polega na reakcji na rozłączenie relacji. Na przykład, na przykład podczas ustawiania pola adresu na
null
lub na innyAddress
obiekt.Jeśli
orphanRemoval=true
jest określony, odłączoneAddress
wystąpienie jest automatycznie usuwane. Jest to przydatne do czyszczenia zależnych obiektów (np.Address
), Które nie powinny istnieć bez odniesienia do obiektu właściciela (npEmployee
.).Jeśli tylko
cascade=CascadeType.REMOVE
jest określony, nie są podejmowane żadne automatyczne działania, ponieważ rozłączenie relacji nie jest operacją usuwania.Aby uniknąć wiszących odniesień w wyniku usunięcia osieroconych, ta funkcja powinna być włączona tylko dla pól, które przechowują prywatne niepodzielne obiekty zależne.
Mam nadzieję, że to wyjaśni.
źródło
W chwili usunięcia encji podrzędnej z kolekcji usuniesz również encję podrzędną z bazy danych. orphanRemoval oznacza również, że nie możesz zmienić rodziców; jeśli istnieje dział, który ma pracowników, po usunięciu tego pracownika, aby umieścić go w innym oddziale, przypadkowo usuniesz tego pracownika z bazy danych przy opróżnianiu / zatwierdzaniu (w zależności od tego, co nastąpi wcześniej). Morale polega na ustawieniu sierociRemovala na wartość prawdy, o ile masz pewność, że dzieci tego rodzica nie będą migrować do innego rodzica przez cały czas ich istnienia. Włączenie sierocińcaRemoval automatycznie dodaje również USUŃ do listy kaskad.
źródło
department.remove(emp);
, pracownik zostanie usunięty z tabeli emp nawet bez połączeniacommit()
Równoważne mapowanie JPA dla DDL
ON DELETE CASCADE
tocascade=CascadeType.REMOVE
. Usunięcie sieroty oznacza, że jednostki zależne są usuwane, gdy związek z ich „macierzystą” jednostką zostaje zniszczony. Na przykład, jeśli dziecko jest usuwane z@OneToMany
relacji bez jawnego usuwania go w menedżerze encji.źródło
cascade=CascadeType.REMOVE
NIE jest równoważne zON DELETE CASCADE
. On do remove w kodzie aplikacji i nie wpływa na DDL, inne wykonywane w DB. Zobacz stackoverflow.com/a/19696859/548473Różnica polega na:
- orphanRemoval = true: „Podrzędny” byt jest usuwany, gdy nie jest już przywoływany (jego rodzic nie może zostać usunięty).
- CascadeType.REMOVE: Podmiot „podrzędny” jest usuwany tylko po usunięciu jego „nadrzędny”.
źródło
Przejścia stanu encji
JPA tłumaczy przejścia stanu encji na instrukcje SQL, takie jak INSERT, UPDATE lub DELETE.
Kiedy jesteś
persist
bytem, planujesz wykonanie instrukcji INSERT po jejEntityManager
opróżnieniu, automatycznie lub ręcznie.gdy jesteś
remove
bytem, planujesz instrukcję DELETE, która zostanie wykonana po opróżnieniu kontekstu trwałości.Kaskadowe przejścia stanu encji
Dla wygody JPA pozwala propagować przejścia stanu encji z encji nadrzędnych na encje podrzędne.
Jeśli więc masz
Post
jednostkę nadrzędną , która jest@OneToMany
powiązana zPostComment
jednostką podrzędną:comments
Kolekcja wPost
jednostce są odwzorowywane w sposób następujący:CascadeType.ALL
Ten
cascade
atrybut informuje dostawcę JPA, aby przekazał przejście stanu encji zPost
encji nadrzędnej do wszystkichPostComment
encji zawartych w plikucomments
kolekcji.Jeśli więc usuniesz
Post
jednostkę:Dostawca JPA
PostComment
najpierw usunie encję, a kiedy wszystkie encje podrzędne zostaną usunięte, usunie równieżPost
encję:Usunięcie sieroty
Po ustawieniu
orphanRemoval
atrybututrue
dostawca JPA planujeremove
operację, gdy jednostka potomna zostanie usunięta z kolekcji.W naszym przypadku
Dostawca JPA usunie powiązany
post_comment
rekord, ponieważPostComment
jednostka nie jest już przywoływana wcomments
kolekcji:PRZY USUNIĘCIU KASKADA
ON DELETE CASCADE
Jest określona na poziomie FK:Gdy to zrobisz, jeśli usuniesz
post
wiersz:Wszystkie powiązane
post_comment
jednostki są automatycznie usuwane przez silnik bazy danych. Może to być jednak bardzo niebezpieczna operacja, jeśli przez pomyłkę usuniesz element główny.Wniosek
Zaletą JPA
cascade
iorphanRemoval
opcji jest to, że możesz również skorzystać z optymistycznego blokowania, aby zapobiec utracie aktualizacji .Jeśli korzystasz z mechanizmu kaskadowego JPA, nie musisz używać poziomu DDL
ON DELETE CASCADE
, co może być bardzo niebezpieczną operacją, jeśli usuniesz element główny, który ma wiele elementów potomnych na wielu poziomach.Więcej informacji na ten temat można znaleźć w tym artykule .
źródło
CascadeType
. To mechanizm uzupełniający. Teraz mylicie usuwanie z utrzymywaniem się. Usuwanie Sierot polega na usuwaniu niepowiązanych powiązań, a utrwalanie polega na zapisywaniu nowych encji. Aby uzyskać lepsze zrozumienie tych pojęć, należy skorzystać z łączy podanych w odpowiedzi.@GaryK odpowiedź jest absolutnie świetna, spędziłem godzinę szukając wyjaśnienia
orphanRemoval = true
vsCascadeType.REMOVE
i pomogło mi to zrozumieć.Podsumowując:
orphanRemoval = true
działa identycznie jakCascadeType.REMOVE
TYLKO JEŚLIentityManager.delete(object)
usuwamy obiekt ( ) i chcemy również usunąć obiekty potomne.W zupełnie innej sytuacji, gdy pobieramy niektóre dane, takie jak,
List<Child> childs = object.getChilds()
a następnie usuwamy child (entityManager.remove(childs.get(0)
), użycieorphanRemoval=true
spowoduje, że odpowiadająca mu encjachilds.get(0)
zostanie usunięta z bazy danych.źródło
usuwanie osieroconych ma taki sam efekt jak w przypadku USUŃ KASKADĘ w następującym scenariuszu: - Załóżmy, że mamy prostą relację wiele do jednego między jednostką studencką a jednostką prowadzącą, w której wielu studentów można zmapować na ten sam przewodnik, aw bazie danych mamy relacja klucza obcego między tabelą Studenta a Przewodnikiem, dzięki czemu tabela studenta ma identyfikator id_guide jako FK.
// Jednostka nadrzędna
W tym scenariuszu relacja polega na tym, że jednostka studencka jest właścicielem relacji i jako taka musimy zapisać jednostkę studencką, aby zachować cały wykres obiektu, np.
Tutaj mapujemy ten sam przewodnik z dwoma różnymi obiektami studenckimi, a ponieważ używany jest CASCADE.PERSIST, wykres obiektów zostanie zapisany jak poniżej w tabeli bazy danych (w moim przypadku MySql)
Stół STUDENT: -
ID Nazwa Dział Id_Guide
1 Roy ECE 1
2 Nick ECE 1
Tabela GUIDE: -
NAZWA ID Wynagrodzenie
1 John 1500 USD
a teraz, jeśli chcę usunąć jednego z uczniów, używając
a po usunięciu rekordu studenta należy również usunąć odpowiedni rekord przewodnika, to tutaj pojawia się atrybut CASCADE.REMOVE w jednostce Studenta i to, co robi, usuwa ucznia o identyfikatorze 1 oraz odpowiedni obiekt przewodnika (identyfikator 1). Ale w tym przykładzie jest jeszcze jeden obiekt ucznia, który jest odwzorowany na ten sam rekord przewodnika i jeśli nie użyjemy atrybutu sierotaRemoval = true w elemencie przewodnika, powyższy kod usuwania nie będzie działał.
źródło