Ok, więc to prawdopodobnie trywialne pytanie, ale mam problem z wizualizacją i zrozumieniem różnic i kiedy ich używać. Nie mam też pewności, w jaki sposób koncepcje takie jak odwzorowania jednokierunkowe i dwukierunkowe wpływają na relacje jeden do wielu / wiele do wielu. Używam teraz Hibernacji, więc wszelkie wyjaśnienia związane z ORM będą pomocne.
Jako przykład załóżmy, że mam następującą konfigurację:
public class Person{
private Long personId;
private Set<Skill> skills;
//Getters and setters
}
public class Skill{
private Long skillId;
private String skillName;
//Getters and setters
}
Więc w tym przypadku jaki rodzaj mapowania miałbym? Odpowiedzi na ten konkretny przykład są zdecydowanie doceniane, ale bardzo chciałbym również omówić, kiedy należy używać opcji jeden do wielu i wiele do wielu, a kiedy używać tabeli łączenia w porównaniu z kolumną łączenia i jednokierunkowej i dwukierunkowej.
java
hibernate
orm
many-to-many
one-to-many
Ian Dallas
źródło
źródło
Odpowiedzi:
Jeden do wielu : jedna osoba ma wiele umiejętności, umiejętność nie jest ponownie używana między osobami
Wiele do wielu : jedna osoba ma wiele umiejętności, umiejętność jest ponownie używana między osobami
W relacji jeden do wielu jeden obiekt jest „rodzicem”, a drugi „dzieckiem”. Rodzic kontroluje istnienie dziecka. W przypadku wielu do wielu istnienie któregokolwiek typu jest zależne od czegoś spoza nich obu (w szerszym kontekście aplikacji).
Twój temat (domena) powinien dyktować, czy relacja jest typu jeden do wielu, czy też wiele do wielu - jednak uważam, że uczynienie relacji jednokierunkowej lub dwukierunkowej jest decyzją inżynieryjną, która ogranicza pamięć, przetwarzanie, wydajność itp.
Co może być mylące, to fakt, że dwukierunkowa relacja wiele do wielu nie musi być symetryczna! Oznacza to, że grupa ludzi może wskazać umiejętność, ale umiejętność nie musi odnosić się tylko do tych osób. Zwykle tak, ale taka symetria nie jest wymagana. Weźmy na przykład miłość - jest dwukierunkowa („I-Love”, „Loves-Me”), ale często asymetryczna („Kocham ją, ale ona mnie nie kocha”)!
Wszystkie są dobrze obsługiwane przez Hibernate i JPA. Pamiętaj tylko, że Hibernate ani żaden inny ORM nie przejmują się utrzymywaniem symetrii podczas zarządzania dwukierunkowymi relacjami wiele do wielu ... to wszystko zależy od aplikacji.
źródło
Wygląda na to, że wszyscy odpowiadają
One-to-many
vsMany-to-many
.:Różnica pomiędzy
One-to-many
,Many-to-one
aMany-to-Many
to:One-to-many
vsMany-to-one
to kwestia perspektywy .Unidirectional
vsBidirectional
nie wpłynie na mapowanie, ale wpłynie na sposób uzyskania dostępu do danych.Many-to-one
tejmany
stronie będzie zachować odniesienie doone
boku. Dobrym przykładem jest „Państwo ma miasta”. W tym przypadkuState
jest to jedna strona iCity
jest wiele stron. Wstate_id
tabeli pojawi się kolumnacities
.One-to-Many
jednej strony będzie naszym punktem odniesienia. Na przykład „Użytkownik ma adresy”. W tym przypadku możemy mieć trzy kolumnyaddress_1_id
,address_2_id
iaddress_3_id
albo spojrzeć w górę tabeli z wyjątkowej presji nauser_id
iaddress_id
.Many-to-Many
członkach każdej strony może mieć odniesienie do dowolnej liczby członków drugiej strony. Aby to osiągnąć, używana jest tabela przeglądowa . Przykładem tego są relacje między lekarzami i pacjentami. Lekarz może mieć wielu pacjentów i odwrotnie.źródło
s.persons
, bo jest tylkos.person
One-to-many
relacja, jaką opisujesz, jestMany-to-many
relacją, ponieważperson
odnosi się do wielu,skills
aleskill
nie odnosi się do konkretnej osoby, a wiele z nichpersons
może mieć takie samo odniesienieskill
. A twójMany-to-one
związek jest tak naprawdę,One-to-many
ponieważ każda umiejętność ma odniesienie tylko do jednej,person
ponieważ dziecko ma tylko jedną matkę.skills
mająperson_id
), wtedy nazywasz to „Jeden do wielu”, ale kiedy jest to strona „Wiele” (użytkownicy i adresy,users
maaddress_id
), wtedy nazywasz to Wielu do jednego. Ale strukturalnie oba przypadki są identyczne i nazywane jeden-do-wielu.1) Kręgi to Entities / POJOs / Beans
2) deg jest skrótem od stopnia jak na wykresach (liczba krawędzi)
PK = klucz podstawowy, FK = klucz obcy
Zwróć uwagę na sprzeczność między stopniem a nazwą strony. Wiele odpowiada stopniowi = 1, podczas gdy jeden odpowiada stopniowi> 1.
źródło
Spójrz na ten artykuł: Mapowanie relacji między obiektami
źródło
this occurs when the maximum of one multiplicity is one and the other is greater than one
lolwut?Jeden za dużo
Relacja jeden do wielu tabel wygląda następująco:
W systemie relacyjnej bazy danych relacja między tabelami jeden do wielu łączy dwie tabele na podstawie
Foreign Key
kolumny podrzędnej, która odwołuje sięPrimary Key
do wiersza tabeli nadrzędnej.Na powyższym diagramie tabeli
post_id
kolumna wpost_comment
tabeli maForeign Key
związek z kolumnąpost
identyfikatora tabeliPrimary Key
:Adnotacja @ManyToOne
Najlepszym sposobem odwzorowania relacji jeden do wielu w tabeli jest użycie
@ManyToOne
adnotacji.W naszym przypadku encja podrzędna
PostComment
mapujepost_id
kolumnę klucza obcego za pomocą@ManyToOne
adnotacji:Korzystanie z
@OneToMany
adnotacji JPATylko dlatego, że masz możliwość korzystania z
@OneToMany
adnotacji, nie oznacza to, że powinna to być opcja domyślna dla każdego typu „ jeden do wielu” relacji bazie danych. Problem z kolekcjami polega na tym, że możemy ich używać tylko wtedy, gdy liczba rekordów podrzędnych jest raczej ograniczona.Najlepszym sposobem na zmapowanie
@OneToMany
powiązania jest poleganie na@ManyToOne
stronie przy propagowaniu wszystkich zmian stanu encji:Jednostka nadrzędna
Post
posiada dwie metody narzędziowe (np.addComment
IremoveComment
), które są używane do synchronizacji obu stron dwukierunkowego powiązania. Zawsze powinieneś podawać te metody, gdy pracujesz z asocjacją dwukierunkową, ponieważ w przeciwnym razie ryzykujesz bardzo subtelnymi problemami z propagacją stanu .Należy
@OneToMany
unikać skojarzenia jednokierunkowego, ponieważ jest mniej wydajne niż użycie@ManyToOne
lub@OneToMany
skojarzenie dwukierunkowe .Jeden na jednego
Relacja jeden do jednego tabeli wygląda następująco:
W systemie relacyjnej bazy danych relacja między tabelami jeden do jednego łączy dwie tabele na podstawie
Primary Key
kolumny w potomku, która jest równieżForeign Key
odwołaniem doPrimary Key
wiersza tabeli nadrzędnej.Dlatego możemy powiedzieć, że tabela podrzędna współdzieli
Primary Key
tabelę nadrzędną.Na powyższym diagramie tabeli
id
kolumna wpost_details
tabeli ma równieżForeign Key
związek z kolumnąpost
tabeliid
Primary Key
:Używanie JPA
@OneToOne
z@MapsId
adnotacjamiNajlepszym sposobem odwzorowania
@OneToOne
relacji jest użycie@MapsId
. W ten sposób nie potrzebujesz nawet powiązania dwukierunkowego, ponieważ zawsze możesz pobraćPostDetails
jednostkę za pomocąPost
identyfikatora jednostki.Mapowanie wygląda następująco:
[code language = "java"] @Entity (name = "PostDetails") @Table (name = "post_details") public class PostDetails {
} [/kod]
W ten sposób
id
właściwość służy zarówno jako klucz podstawowy, jak i klucz obcy. Zauważysz, że@Id
kolumna nie używa już@GeneratedValue
adnotacji, ponieważ identyfikator jest wypełniony identyfikatorempost
powiązania.Wiele do wielu
Relacja między tabelami wiele do wielu wygląda następująco:
W systemie relacyjnej bazy danych relacja wiele-do-wielu tabel łączy dwie tabele nadrzędne za pośrednictwem tabeli podrzędnej, która zawiera dwie
Foreign Key
kolumny odwołujące się doPrimary Key
kolumn dwóch tabel nadrzędnych.Na powyższym schemacie tabeli
post_id
kolumna wpost_tag
tabeli ma równieżForeign Key
związek z kolumnąpost
id tabeliPrimary Key
:A
tag_id
kolumna wpost_tag
tabeli maForeign Key
związek z kolumnątag
identyfikatora tabeliPrimary Key
:Korzystanie z
@ManyToMany
mapowania JPAOto jak można odwzorować
many-to-many
relacje między tabelami za pomocą JPA i Hibernate:tags
Stowarzyszenie wPost
jednostce określa tylkoPERSIST
iMERGE
kaskadowych typy. Jak wyjaśniono w tym artykule ,REMOVE
zmiana stanu jednostki nie ma żadnego sensu w przypadku@ManyToMany
powiązania JPA, ponieważ może spowodować usunięcie łańcucha, które ostatecznie wymazałoby obie strony skojarzenia.Post
Jednostka wykorzystuje identyfikator podmiotu, na rzecz równości, ponieważ brakuje żadnego unikalnego klucza biznesowego. Jak wyjaśniono w tym artykule , możesz użyć identyfikatora jednostki dla równości, o ile upewnisz się, że pozostaje on spójny we wszystkich przejściach stanu jednostki .Tag
Jednostka posiada unikalny klucz przedsiębiorcy, który jest oznaczony Hibernate specyficznych@NaturalId
adnotacji. W takim przypadku unikalny klucz biznesowy jest najlepszym kandydatem do kontroli równości .mappedBy
Atrybutemposts
zrzeszania się wTag
znakach podmiot, który w tym dwukierunkowej relacji,Post
jednostka posiada stowarzyszenie. Jest to potrzebne, ponieważ tylko jedna strona może być właścicielem relacji, a zmiany są propagowane do bazy danych tylko z tej konkretnej strony.Set
być preferowany, ponieważ używanieList
with@ManyToMany
jest mniej wydajne.źródło
prawdopodobnie wymagałoby to powiązania wielu do wielu, jak następuje
być może będziesz musiał zdefiniować joinTable + JoinColumn, ale będzie to możliwe również bez ...
źródło
Tak bym wyjaśnił:
OneToOne - Relacja OneToOne
OneToMany - ManyToOne związku
Relacja ManyToMany - ManyToMany
źródło
Przede wszystkim przeczytaj wszystko drobnym drukiem. Zauważ, że NHibernate (a więc zakładam, że również Hibernate) mapowanie relacyjne ma zabawny związek z mapowaniem DB i mapowaniem wykresów obiektów. Na przykład relacje jeden do jednego są często implementowane jako relacja wiele do jednego.
Po drugie, zanim będziemy mogli powiedzieć ci, jak powinieneś napisać swoją mapę O / R, musimy również zobaczyć twoją bazę danych. W szczególności, czy jedną Umiejętność może posiadać wiele osób? Jeśli tak, masz relację wiele do wielu; w przeciwnym razie jest wiele do jednego.
Po trzecie, wolę nie implementować bezpośrednio relacji wiele-do-wielu, ale zamiast tego zamodelować „tabelę złączeń” w modelu domeny - tj. Traktuj ją jako jednostkę, na przykład:
Więc widzisz, co masz? Masz dwie relacje jeden do wielu. (W tym przypadku Osoba może mieć zbiór Umiejętności Person, ale nie miałby zbioru Umiejętności). Jednak niektórzy wolą używać relacji wiele do wielu (między Osobą a Umiejętnością); to jest kontrowersyjne.
Po czwarte, jeśli masz relacje dwukierunkowe (np. Nie tylko Osoba ma zbiór Umiejętności, ale także Umiejętność ma kolekcję Osób), NHibernate nie wymusza dwukierunkowości w Twoim BL; rozumie tylko dwukierunkowość relacji dla celów trwałości.
Po piąte, wiele do jednego jest dużo łatwiejsze do poprawnego użycia w NHibernate (i zakładam, że Hibernate) niż jeden do wielu (mapowanie kolekcji).
Powodzenia!
źródło