W sekcji przykładowej @OneToMany
adnotacji JPA :
Przykład 1-59 @OneToMany - klasa klienta z typami generycznymi
@Entity
public class Customer implements Serializable {
...
@OneToMany(cascade=ALL, mappedBy="customer")
public Set<Order> getOrders() {
return orders;
}
...
}
Przykład 1-60 @ManyToOne - Order Class with Generics
@Entity
public class Order implements Serializable {
...
@ManyToOne
@JoinColumn(name="CUST_ID", nullable=false)
public Customer getCustomer() {
return customer;
}
...
}
Wydaje mi się, że Customer
podmiot jest właścicielem stowarzyszenia. Jednak w wyjaśnieniu mappedBy
atrybutu w tym samym dokumencie jest napisane, że:
jeśli relacja jest dwukierunkowa, ustaw element mappedBy po odwrotnej (nie będącej właścicielem) stronie powiązania na nazwę pola lub właściwości będącej właścicielem relacji, jak pokazano na przykładzie 1-60.
Jeśli się jednak nie mylę, w przykładzie wygląda na to, że w mappedBy
rzeczywistości jest on określony po stronie będącej właścicielem, a nie po stronie niebędącej właścicielem.
Więc moje pytanie jest w zasadzie:
Która z jednostek jest właścicielem w powiązaniu dwukierunkowym (jeden do wielu / wiele do jednego)? Jak możemy wyznaczyć Stronę Jedną jako właściciela? Jak możemy wyznaczyć Stronę Wielu jako właściciela?
Co należy rozumieć przez „odwrotną stronę skojarzenia”? Jak możemy wyznaczyć Jedną stronę jako odwrotną? Jak możemy wyznaczyć stronę Wielu jako przeciwieństwo?
Odpowiedzi:
Aby to zrozumieć, musisz cofnąć się o krok. W OO klient jest właścicielem zamówień (zamówienia są listą w obiekcie klienta). Nie może być zamówienia bez klienta. Więc klient wydaje się być właścicielem zamówień.
Ale w świecie SQL jeden element będzie zawierał wskaźnik do drugiego. Ponieważ istnieje 1 klient dla zamówień N, każde zamówienie zawiera klucz obcy klienta, do którego należy. To jest „połączenie”, a to oznacza, że zamówienie „jest właścicielem” (lub dosłownie zawiera) połączenie (informacje). To jest dokładnie odwrotne od świata OO / modelowego.
Może to pomóc zrozumieć:
Odwrotną stroną jest OO „właściciel” obiektu, w tym przypadku klient. Klient nie ma kolumn w tabeli do przechowywania zamówień, więc musisz wskazać mu, gdzie w tabeli zamówień może zapisać te dane (co dzieje się za pośrednictwem
mappedBy
).Innym częstym przykładem są drzewa z węzłami, którymi mogą być zarówno rodzice, jak i dzieci. W tym przypadku te dwa pola są używane w jednej klasie:
Wyjaśnia to projekt „klucza obcego” typu „wiele do jednego”. Istnieje drugie podejście, które wykorzystuje inną tabelę do utrzymania relacji. Oznacza to, że w naszym pierwszym przykładzie masz trzy tabele: jedną z klientami, drugą z zamówieniami i dwukolumnową tabelę z parami kluczy podstawowych (customerPK, orderPK).
To podejście jest bardziej elastyczne niż to powyżej (może z łatwością obsługiwać jeden do jednego, wiele do jednego, jeden do wielu, a nawet wiele do wielu). Cena jest taka
Dlatego rzadko polecam to podejście.
źródło
@Parent
lub@Child
zamiast „XtoY”, aby określić, co oznacza połączenie (a nie jak jest zaimplementowane )Niewiarygodne, że w ciągu 3 lat nikt nie odpowiedział na twoje doskonałe pytanie z przykładami obu sposobów odwzorowania relacji.
Jak wspominali inni, strona „właściciela” zawiera wskaźnik (klucz obcy) w bazie danych. Możesz wyznaczyć dowolną stronę jako właściciela, jednak jeśli wyznaczysz jedną stronę jako właściciela, relacja nie będzie dwukierunkowa (odwrotność, czyli „wiele” stron, nie będzie wiedziała o swoim „właścicielu”). Może to być pożądane w przypadku hermetyzacji / luźnego połączenia:
Jedynym rozwiązaniem do mapowania dwukierunkowego jest posiadanie wskaźnika „wiele” na stronie „jeden” i użycie atrybutu @OneToMany „mappedBy”. Bez atrybutu „mappedBy” Hibernate będzie oczekiwał podwójnego mapowania (baza danych będzie zawierała zarówno kolumnę złączenia, jak i tabelę złączeń, co jest zbędne (zwykle niepożądane).
źródło
Jednostka, która ma tabelę z kluczem obcym w bazie danych, jest jednostką będącą właścicielem, a wskazana druga tabela jest jednostką odwrotną.
źródło
Proste zasady relacji dwukierunkowych:
W przypadku relacji dwukierunkowych typu „wiele do jednego” strona wielu jest zawsze właścicielem relacji. Przykład: 1 pokój ma wiele osób (osoba należy tylko do jednego pokoju) -> stroną właściciela jest osoba
2. W przypadku relacji dwukierunkowych jeden do jednego strona będąca właścicielem odpowiada stronie zawierającej odpowiedni klucz obcy.
W przypadku relacji dwukierunkowych wiele-do-wielu, właścicielem może być każda ze stron.
Hope może ci pomóc.
źródło
Dla dwóch klas jednostek Customer and Order, hibernacja utworzy dwie tabele.
Możliwe przypadki:
mappedBy nie jest używany w Customer.java i Order.java Class then->
Po stronie klienta zostanie utworzona nowa tabela [name = CUSTOMER_ORDER], która będzie nadal mapować CUSTOMER_ID i ORDER_ID. Są to klucze podstawowe tabel klientów i zamówień. Po stronie zamówienia wymagana jest dodatkowa kolumna, aby zapisać odpowiednie mapowanie rekordów Customer_ID.
mappedBy jest używany w Customer.java [Jak podano w opisie problemu] Teraz dodatkowa tabela [CUSTOMER_ORDER] nie jest tworzona. Tylko jedna kolumna w tabeli zamówień
mappedby jest używany w Order.java Teraz dodatkowa tabela zostanie utworzona przez hibernację. [name = CUSTOMER_ORDER] Tabela zamówień nie będzie miała dodatkowej kolumny [Customer_ID] do mapowania.
Właścicielem relacji może być dowolna strona. Ale lepiej wybrać stronę xxxToOne.
Efekt kodowania -> Tylko właściciel jednostki może zmienić status relacji. W poniższym przykładzie właścicielem relacji jest klasa BoyFriend. nawet jeśli Dziewczyna chce się rozstać, nie może.
źródło
Relacje między tabelami a relacje encji
W systemie relacyjnej bazy danych mogą istnieć tylko trzy typy relacji między tabelami:
Tak więc
one-to-many
relacja między tabelami wygląda następująco:Zauważ, że relacja jest oparta na kolumnie Foreign Key (np.
post_id
) W tabeli podrzędnej.Tak więc istnieje jedno źródło prawdy, jeśli chodzi o zarządzanie
one-to-many
relacjami między stołami.Teraz, jeśli weźmiesz dwukierunkową relację encji, która mapuje na
one-to-many
relację między tabelami, którą widzieliśmy wcześniej:Jeśli spojrzysz na powyższy diagram, zobaczysz, że istnieją dwa sposoby zarządzania tą relacją.
W
Post
jednostce maszcomments
kolekcję:A w
PostComment
Thepost
stowarzyszenie jest odwzorowany w sposób następujący:Masz więc dwie strony, które mogą zmienić powiązanie encji:
comments
kolekcji podrzędnej, nowypost_comment
wiersz powinien zostać powiązany zpost
jednostką nadrzędną za pośrednictwem jejpost_id
kolumny.post
właściwośćPostComment
jednostki,post_id
należy również zaktualizować kolumnę.Ponieważ istnieją dwa sposoby przedstawiania kolumny klucza obcego, należy określić, który jest źródłem prawdy, jeśli chodzi o tłumaczenie zmiany stanu skojarzenia na odpowiadającą jej modyfikację wartości kolumny klucza obcego.
MappedBy (inaczej strona odwrotna)
mappedBy
Atrybut informuje, że@ManyToOne
strona jest odpowiedzialna za zarządzanie kolumny klucz obcy, a zbiór jest używany tylko do pobierania jednostek podrzędnych i kaskady zmian stanu podmiotem dominującym dla dzieci (na przykład usuwając rodzic powinien także usunąć podmioty podrzędne).Zsynchronizuj obie strony skojarzenia dwukierunkowego
Teraz, nawet jeśli zdefiniowałeś
mappedBy
atrybut i@ManyToOne
powiązanie po stronie podrzędnej zarządza kolumną klucza obcego, nadal musisz zsynchronizować obie strony skojarzenia dwukierunkowego.Najlepszym sposobem na to jest dodanie dwóch metod narzędziowych:
addComment
IremoveComment
metody zapewnienia, że obie strony są zsynchronizowane. Tak więc, jeśli dodamy jednostkę podrzędną, jednostka podrzędna musi wskazywać na jednostkę nadrzędną, a jednostka nadrzędna powinna zawierać element podrzędny w kolekcji podrzędnej.źródło