2012-10-23 48 views
132

Myślę, że brakuje mi zrozumienia znaczenia kaskadowania w kontekście relacji @ManyToOne.JPA @ManyToOne z CascadeType.ALL

postępowania:

public class User { 

    @OneToMany(fetch = FetchType.EAGER) 
    protected Set<Address> userAddresses; 

} 

public class Address { 

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) 
    protected User addressOwner; 

} 

Jaki jest sens cascade = CascadeType.ALL? Na przykład, jeśli usunę pewien adres z bazy danych, w jaki sposób fakt, że dodałem numer cascade = CascadeType.ALL wpływa na moje dane (według mnie)?

Odpowiedz

230

Znaczenie CascadeType.ALL jest takie, że trwałość będzie propagować (kaskadować) wszystkie operacje EntityManager (PERSIST, REMOVE, REFRESH, MERGE, DETACH) do powiązanych elementów.

Wygląda na to, że jest to zły pomysł, ponieważ usunięcie Address doprowadziłoby do usunięcia powiązanego User. Ponieważ użytkownik może mieć wiele adresów, pozostałe adresy stałyby się sierotami. Jednak odwrotny przypadek (opisywanie wartości User) ma sens - jeśli adres należy do tylko jednego użytkownika, bezpieczne jest propagowanie usuwania wszystkich adresów należących do użytkownika, jeśli ten użytkownik zostanie usunięty.

BTW: możesz dodać atrybut mappedBy="addressOwner" do swojego User, aby zasygnalizować dostawcy uporczywości, że kolumna łączenia powinna znajdować się w tabeli ADRES.

+27

+1 za najlepsze i najkrótsze wyjaśnienie mappeyBy, z jakim kiedykolwiek miałem do czynienia. – Ridcully

+3

Dobrze byłoby mieć CascadeType.ALL na stronie @OneToMany. – mvmn

33

See here na przykład z dokumentacji OpenJPA. CascadeType.ALL oznacza, że ​​wykona wszystkie czynności.

Cytat:

CascadeType.PERSIST: Przy utrzymującej się podmiot, również utrzymują podmioty posiadane w tej dziedzinie. Sugerujemy liberalne zastosowanie tej reguły kaskadowej, ponieważ jeśli EntityManager znajdzie pole, które odwołuje się do nowej jednostki podczas spłukiwania, a pole nie używa CascadeType.PERSIST, jest to błąd.

CascadeType.REMOVE: Podczas usuwania encji usuń również encje znajdujące się w tym polu.

CascadeType.REFRESH: Podczas odświeżania obiektu należy również odświeżać jednostki znajdujące się w tym polu.

CascadeType.MERGE: Łącząc stan obiektu, połącz także elementy znajdujące się w tym polu.

Sebastian

+3

Nowość w WZP, ta informacja jest przydatna, ale co z tym artykułem? – Sarz

+1

W CascadeType.DETACH, podczas odłączania encji, em również odłącza jednostki posiadane przez nadrzędną jednostkę. –

15

From the EJB3.0 Specification:

Zastosowanie elementu adnotacji kaskadowej może być stosowane do namnożenia działanie danej operacji związanych jednostek. Funkcja kaskadowa jest najczęściej używana w relacjach rodzic-dziecko.

Jeśli X jest obiektem zarządzanym, operacja usunięcia powoduje jego usunięcie z . Operacja usuwania jest kaskadowana do jednostek, do których odwołuje się X, , jeśli relacje od X do tych innych obiektów są opatrzone przypisami o wartości kaskady = REMOVE lub cascade = ALL wartość elementu adnotacji.

Tak w skrócie, relacje podmiotu zdefiniowane z CascadeType.All zapewni, że wszystkie zdarzenia Trwałość takich jak utrzymują, odświeżyć, łączenia i usuwania, które występują na rodzica, zostaną przekazane do dziecka. Zdefiniowanie innych opcji zapewnia deweloperowi bardziej szczegółowy poziom kontroli nad powiązaniem encji w utrzymywaniu.

Na przykład, gdy miałem obiektową książkę zawierającą listę stron i dodałem obiekt strony na tej liście. Jeśli adnotacja @OneToMany określająca powiązanie między książką a stroną jest oznaczona jako CascadeType.All, utrwalenie księgi spowoduje, że strona również zostanie utrwalona w bazie danych.

8

W JPA 2.0, jeśli chcesz usunąć adres, jeśli usunąłeś go z jednostki użytkownika, możesz dodać orphanRemoval=true (zamiast CascadeType.REMOVE) do swojego @OneToMany.

Więcej wyjaśnień między orphanRemoval=true i CascadeType.REMOVE jest here.

6

Jak wyjaśniono w this article iw mojej książce High-Performance Java Persistence należy nigdy używać CascadeType.ALL na @ManyToOne od entity state transitions powinny propagować od podmiotów dominujących do tych podrzędnych.

Strona @ManyToOne jest zawsze powiązana z dzieckiem, ponieważ powinna odwzorować leżące u jej podstaw FK.

Dlatego przesunąć CascadeType.ALL od stowarzyszenia do @OneToMany który powinien wykorzystać atrybut mappedBy ponieważ jest the most efficient one-to-many mapping@ManyToOne. `