Jaka jest różnica pomiędzy:
@Entity
public class Company {
@OneToMany(cascade = CascadeType.ALL , fetch = FetchType.LAZY)
@JoinColumn(name = "companyIdRef", referencedColumnName = "companyId")
private List<Branch> branches;
...
}
i
@Entity
public class Company {
@OneToMany(cascade = CascadeType.ALL , fetch = FetchType.LAZY, mappedBy = "companyIdRef")
private List<Branch> branches;
...
}
Odpowiedzi:
Adnotacja
@JoinColumn
wskazuje, że ta jednostka jest właścicielem relacji (to znaczy: odpowiednia tabela ma kolumnę z kluczem obcym do tabeli, do której istnieje odwołanie), podczas gdy atrybutmappedBy
wskazuje, że jednostka po tej stronie jest odwrotnością relacji, oraz właściciel mieszka w „innym” podmiocie. Oznacza to również, że możesz uzyskać dostęp do drugiej tabeli z klasy, do której dodałeś adnotację „mappedBy” (w pełni dwukierunkowa relacja).W szczególności dla kodu w pytaniu prawidłowe adnotacje wyglądałyby następująco:
źródło
@JoinColumn
wCompany
Branch
nie ma właściwości, do której się odwołujeCompany
, ale tabela bazowa ma taką kolumnę, możesz użyć jej@JoinTable
do odwzorowania. Jest to niezwykła sytuacja, ponieważ normalnie można odwzorować kolumnę w obiekcie, która odpowiada jej tabeli, ale może się zdarzyć i jest całkowicie uzasadniona.@OneToOne
, wiersze podrzędne są aktualizowane za pomocąnull
w kolumnie FKey, która odwołuje się do elementu nadrzędnego.@JoinColumn
może być stosowany po obu stronach relacji. Pytanie dotyczyło używania@JoinColumn
z@OneToMany
boku (rzadki przypadek). Chodzi tutaj o fizyczne powielanie informacji (nazwa kolumny) wraz z niezoptymalizowanym zapytaniem SQL, które wygeneruje dodatkoweUPDATE
instrukcje .Według dokumentacji :
Ponieważ wiele do jednego jest (prawie) zawsze właścicielem strony relacji dwukierunkowej w specyfikacji JPA, powiązanie typu jeden do wielu jest opatrzone adnotacją
@OneToMany(mappedBy=...)
Troop
ma dwukierunkową relację jeden do wieluSoldier
dzięki własności wojska. Nie musisz (nie wolno) definiować żadnego fizycznego mapowania zmappedBy
boku.Aby zmapować dwukierunkowy jeden na wiele, ze stroną jeden do wielu jako właścicielem , musisz usunąć
mappedBy
element i ustawić wiele na jeden@JoinColumn
jakoinsertable
iupdatable
na fałsz. To rozwiązanie nie jest zoptymalizowane i spowoduje wygenerowanie dodatkowychUPDATE
instrukcji.źródło
mappedBy="troop"
odnosi się do którego pola?mappedBy="troop"
odnosi się do żołnierza własności w klasie Żołnierz. W powyższym kodzie właściwość nie jest widoczna, ponieważ tutaj Mykhaylo ją pominął, ale można wywnioskować jej istnienie przez getter getTroop (). Sprawdź odpowiedź Óscara Lópeza , jest bardzo jasna i dostaniesz sens.Jednokierunkowe połączenie jeden do wielu
Jak wyjaśniłem w tym artykule , jeśli używasz
@OneToMany
adnotacji z@JoinColumn
, to masz jednokierunkowe powiązanie, takie jak to międzyPost
jednostką nadrzędną a dzieckiemPostComment
na poniższym diagramie:Podczas korzystania z jednokierunkowego powiązania jeden do wielu, tylko strona nadrzędna mapuje powiązanie.
W tym przykładzie tylko
Post
jednostka zdefiniuje@OneToMany
powiązanie zPostComment
jednostką podrzędną :Dwukierunkowe powiązanie jeden do wielu
Jeśli używasz
@OneToMany
zmappedBy
ustawionym atrybutem, masz dwukierunkowy stowarzyszenie. W naszym przypadku zarównoPost
jednostka ma kolekcjęPostComment
jednostek potomnych, jak iPostComment
jednostka potomna ma odwołanie doPost
jednostki macierzystej , jak pokazano na poniższym diagramie:W
PostComment
jednostki,post
własność jednostka jest odwzorowany w sposób następujący:W
Post
encjicomments
powiązanie jest mapowane w następujący sposób:mappedBy
Atrybut z@OneToMany
odniesieniami adnotacjipost
własności w dziecięcejPostComment
podmiotu i, w ten sposób, Hibernate wie, że stowarzyszenie dwukierunkowa jest kontrolowany przez@ManyToOne
stronę, która jest odpowiedzialna za zarządzanie wartość kolumny klucz obcy tabela ta relacja jest oparta na.W przypadku powiązania dwukierunkowego potrzebne są również dwie metody narzędziowe, takie jak
addChild
iremoveChild
:Te dwie metody zapewniają, że obie strony skojarzenia dwukierunkowego nie są zsynchronizowane. Bez synchronizacji obu końców Hibernacja nie gwarantuje, że zmiany stanu skojarzenia zostaną przeniesione do bazy danych.
Który wybrać?
Jednokierunkowy
@OneToMany
stowarzyszenie nie działa bardzo dobrze , więc należy go unikać.Lepiej jest użyć dwukierunkowego,
@OneToMany
który jest bardziej wydajny .źródło
Adnotacja zmapowana idealnie powinna być zawsze używana po stronie nadrzędnej (klasa firmy) relacji dwukierunkowej, w tym przypadku powinna znajdować się w klasie firmy, wskazując na zmienną składową „firma” klasy podrzędnej (klasa oddziału)
Adnotacja @JoinColumn służy do określenia odwzorowanej kolumny do dołączenia do powiązania encji, adnotacja ta może być używana w dowolnej klasie (nadrzędnej lub podrzędnej), ale idealnie powinna być używana tylko z jednej strony (w klasie nadrzędnej lub w klasie podrzędnej nie w obu) tutaj w tym przypadku użyłem go po stronie podrzędnej (klasa rozgałęzienia) relacji dwukierunkowej wskazującej klucz obcy w klasie rozgałęzienia.
poniżej znajduje się działający przykład:
klasa rodzicielska, firma
klasa dziecięca, oddział
źródło
Chciałbym tylko dodać, że
@JoinColumn
nie zawsze musi to być związane z fizyczną lokalizacją informacji, jak sugeruje ta odpowiedź. Można łączyć@JoinColumn
z,@OneToMany
nawet jeśli tabela nadrzędna nie ma danych tabeli wskazujących na tabelę podrzędną.Jak zdefiniować jednokierunkową relację OneToMany w JPA
Jednokierunkowy OneToMany, bez odwrotnego ManyToOne, bez tabeli łączenia
Wydaje się, że jest dostępny tylko w
JPA 2.x+
. Jest to przydatne w sytuacjach, w których chcesz, aby klasa potomna zawierała tylko identyfikator rodzica, a nie pełny w referencji.źródło
Nie zgadzam się z przyjętą tutaj odpowiedzią Óscara Lópeza. Ta odpowiedź jest niedokładna!
NIE
@JoinColumn
wskazuje, że ten byt jest właścicielem relacji. Zamiast tego robi to@ManyToOne
adnotacja (w jego przykładzie).Adnotacje relacji, takie jak
@ManyToOne
,@OneToMany
i@ManyToMany
powiedz JPA / Hibernate, aby utworzyły mapowanie. Domyślnie odbywa się to poprzez osobną tabelę łączenia.@JoinColumn
MappedBy
Pamiętaj:
MappedBy
jest właściwością adnotacji relacji, których celem jest wygenerowanie mechanizmu powiązania dwóch jednostek, które domyślnie robią to, tworząc tabelę łączenia.MappedBy
zatrzymuje ten proces w jednym kierunku.MappedBy
Mówi się, że nieużywany byt jest właścicielem relacji, ponieważ mechanika odwzorowania jest podyktowana w jego klasie poprzez użycie jednej z trzech adnotacji odwzorowania względem pola klucza obcego. To nie tylko określa charakter odwzorowania, ale także instruuje tworzenie tabeli łączenia. Co więcej, istnieje możliwość wyłączenia tabeli łączenia poprzez zastosowanie adnotacji @JoinColumn nad kluczem obcym, który zamiast tego trzyma go w tabeli encji właściciela.Podsumowując:
@JoinColumn
albo tworzy nową kolumnę łączenia, albo zmienia nazwę istniejącej; podczas gdyMappedBy
parametr współpracuje z adnotacjami relacji drugiej (podrzędnej) klasy w celu utworzenia odwzorowania poprzez tabelę łączenia lub przez utworzenie kolumny klucza obcego w powiązanej tabeli encji właściciela.Aby zilustrować sposób
MapppedBy
działania, rozważ poniższy kod. GdybyMappedBy
parametr został usunięty, Hibernacja utworzyłaby DWIE tabele łączenia! Dlaczego? Ponieważ istnieje symetria w relacjach wiele do wielu, a Hibernacja nie ma uzasadnienia dla wybierania jednego kierunku nad drugim.Dlatego używamy,
MappedBy
aby powiedzieć Hibernacji, wybraliśmy inny byt, aby dyktować mapowanie relacji między dwoma bytami.Dodanie @JoinColumn (name = "driverID") w klasie właściciela (patrz poniżej), uniemożliwi utworzenie tabeli łączenia, a zamiast tego, utworzy kolumnę klucza obcego driverID w tabeli Cars, aby zbudować mapowanie:
źródło
JPA jest warstwowym API, różne poziomy mają własne adnotacje. Najwyższym poziomem jest (1) poziom jednostki, który opisuje trwałe klasy, wtedy masz (2) poziom relacyjnej bazy danych, który zakłada, że jednostki są odwzorowane na relacyjną bazę danych i (3) model Java.
Poziom 1 adnotacje:
@Entity
,@Id
,@OneToOne
,@OneToMany
,@ManyToOne
,@ManyToMany
. Możesz wprowadzić trwałość w swojej aplikacji, korzystając tylko z tych adnotacji wysokiego poziomu. Ale musisz utworzyć bazę danych zgodnie z założeniami JPA. Te adnotacje określają model encji / relacji.Poziom 2 adnotacje:
@Table
,@Column
,@JoinColumn
, ... wpływać na mapowanie od jednostek / właściwości do relacyjnych baz danych, tabel / kolumn, jeśli nie jesteś zadowolony z domyślnych JPA lub jeśli trzeba mapować do istniejącej bazy danych. Adnotacje te mogą być postrzegane jako adnotacje dotyczące implementacji, określają sposób mapowania.Moim zdaniem najlepiej przykleić jak najwięcej do adnotacji na wysokim poziomie, a następnie wprowadzić adnotacje na niższym poziomie w razie potrzeby.
Aby odpowiedzieć na pytania:
@OneToMany
/mappedBy
jest najładniejszy, ponieważ używa tylko adnotacji z domeny encji. Opcja@oneToMany
/@JoinColumn
jest również w porządku, ale używa adnotacji implementacyjnej, gdy nie jest to absolutnie konieczne.źródło
Pozwól mi to uprościć.
Możesz użyć @JoinColumn po obu stronach, niezależnie od mapowania.
Podzielmy to na trzy przypadki.
1) Jednokierunkowe mapowanie z oddziału do firmy.
2) Dwukierunkowe mapowanie od firmy do oddziału.
3) Tylko jednokierunkowe mapowanie od firmy do oddziału.
Zatem każdy przypadek użycia będzie należał do tych trzech kategorii. Pozwól, że wyjaśnię, jak używać @JoinColumn i mappedBy .
1) Jednokierunkowe mapowanie z oddziału do firmy.
Użyj JoinColumn w tabeli oddziałów.
2) Dwukierunkowe mapowanie od firmy do oddziału.
Użyj mappedBy w tabeli firmy, jak opisano w odpowiedzi @Mykhaylo Adamovych.
3) Jednokierunkowe mapowanie od firmy do oddziału.
Wystarczy użyć @JoinColumn w tabeli firmowej .
Mówi to, że w oparciu o mapowanie klucza obcego „courseId” w tabeli gałęzi, otrzymam listę wszystkich gałęzi. UWAGA: w tym przypadku nie można pobrać firmy z oddziału, istnieje tylko jednokierunkowe odwzorowanie z firmy na oddział.
źródło