Jakie jest znaczenie CascadeType.ALL dla stowarzyszenia @ManyToOne JPA

210

Myślę, że źle zrozumiałem znaczenie kaskadowania w kontekście @ManyToOnezwiązku.

Walizka:

public class User {

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

}

public class Address {

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

}

Jakie jest znaczenie tego cascade = CascadeType.ALL? Na przykład, jeśli usunę określony adres z bazy danych, w jaki sposób fakt, że dodałem, cascade = CascadeType.ALLwpływa na moje dane ( Userjak sądzę)?

za
źródło

Odpowiedzi:

360

Oznacza CascadeType.ALLto, że trwałość będzie propagować (kaskadowo) wszystkie EntityManageroperacje ( PERSIST, REMOVE, REFRESH, MERGE, DETACH) do powiązanych jednostek.

W twoim przypadku wydaje się to złym pomysłem, ponieważ usunięcie i Addressprowadziłoby do usunięcia powiązanych User. Ponieważ użytkownik może mieć wiele adresów, pozostałe adresy staną się sierotami. Jednak odwrotny przypadek (oznaczenie User) miałby sens - jeśli adres należy tylko do jednego użytkownika, można bezpiecznie propagować usunięcie wszystkich adresów należących do użytkownika, jeśli ten użytkownik zostanie usunięty.

BTW: możesz dodać do swojego mappedBy="addressOwner"atrybutu, aby Userzasygnalizować dostawcy trwałości, że kolumna łączenia powinna znajdować się w tabeli ADRES.

kostja
źródło
55
+1 za najlepsze i najkrótsze objaśnienie mapowania Przez jakie kiedykolwiek spotkałem.
Ridcully
4
Dobrze byłoby mieć CascadeType.ALL po stronie @OneToMany.
mvmn
48

Zobacz tutaj przykład z dokumentów OpenJPA. CascadeType.ALLoznacza, że ​​wykona wszystkie działania.

Zacytować:

CascadeType.PERSIST: Podczas utrwalania encji należy również zachować encje przechowywane w jej polach. Sugerujemy liberalne zastosowanie tej reguły kaskady, ponieważ jeśli EntityManager znajdzie pole, które odwołuje się do nowej encji podczas opróżniania, a pole nie używa CascadeType.PERSIST, jest to błąd.

CascadeType.REMOVE: Usuwając encję, usuwa również encje przechowywane w tym polu.

CascadeType.REFRESH: Odświeżając encję, odśwież również encje przechowywane w tym polu.

CascadeType.MERGE: Podczas scalania stanu encji również scalaj encje przechowywane w tym polu.

Sebastian

seba.wagner
źródło
4
Nowość w JPA, ta informacja jest przydatna, ale co z Detach tutaj?
Sarz
1
W CascadeType.DETACH, podczas odłączania bytu, odłączają również byty będące w posiadaniu bytu nadrzędnego.
Dorian Mejer
29

Jak wyjaśniono w tym artykule oraz w mojej książce, wysoka wydajność Java Persistence , nie należy używać CascadeType.ALLna @ManyToOneod przejścia państwowych jednostka powinna propagować od podmiotów dominujących na nich dziecka, nie na odwrót.

@ManyToOneStrona jest zawsze stowarzyszenie Dziecko od odwzorowuje to pod spodem kolumny klucz obcy.

Dlatego należy przenieść CascadeType.ALLze @ManyToOnestowarzyszenia do @OneToManystrony, która powinna również użyć mappedByatrybutu, ponieważ jest to najbardziej efektywne odwzorowanie relacji tabeli jeden-do-wielu .

Vlad Mihalcea
źródło
18

Ze specyfikacji EJB3.0 :

Użycie kaskadowego elementu adnotacji może być wykorzystane do propagowania efektu operacji do powiązanych jednostek. Funkcja kaskady jest najczęściej używana w relacjach rodzic-dziecko.

Jeśli X jest jednostką zarządzaną, operacja usuwania powoduje jej usunięcie. Operacja usuwania jest kaskadowo dodawana do encji, do których odwołuje się X, jeśli relacje między X a tymi innymi encji są opatrzone adnotacją o wartości elementu kaskady = USUŃ lub kaskady = WSZYSTKIE.

Krótko mówiąc, relacje encji zdefiniowane za pomocą CascadeType.Allzapewnią, że wszystkie zdarzenia utrwalania, takie jak utrwalanie, odświeżanie, scalanie i usuwanie, które występują na rodzicu, zostaną przekazane do dziecka. Zdefiniowanie innych CascadeTypeopcji zapewnia deweloperowi bardziej szczegółowy poziom kontroli nad tym, jak powiązanie encji obsługuje trwałość.

Na przykład, gdybym miał obiekt Book zawierający Listę stron i dodam obiekt strony na tej liście. Jeśli @OneToManyadnotacja definiująca powiązanie między Książką a Stroną zostanie oznaczona jako CascadeType.All, utrwalenie Książki spowoduje utrwalenie Strony również w bazie danych.

Kevin Bowersox
źródło
11

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

Więcej wyjaśnień pomiędzy orphanRemoval=truei CascadeType.REMOVEjest tutaj .

Emilien Brigand
źródło
4

Jeśli chcesz tylko usunąć adres przypisany do użytkownika i nie wpływać na klasę encji User, powinieneś spróbować czegoś takiego:

@Entity
public class User {
   @OneToMany(mappedBy = "addressOwner", cascade = CascadeType.ALL)
   protected Set<Address> userAddresses = new HashSet<>();
}

@Entity 
public class Addresses {
   @ManyToOne(cascade = CascadeType.REFRESH) @JoinColumn(name = "user_id")
   protected User addressOwner;
}

W ten sposób nie musisz się martwić korzystaniem z funkcji pobierania w adnotacjach. Pamiętaj jednak, że usuwając użytkownika usuniesz również podłączony adres do obiektu użytkownika.

szachMati
źródło