Dlaczego pojęcie strony będącej właścicielem jest konieczne:
Idea strony właścicielskiej relacji dwukierunkowej bierze się stąd, że w relacyjnych bazach danych nie ma relacji dwukierunkowych, jak w przypadku obiektów. W bazach danych mamy tylko relacje jednokierunkowe - klucze obce.
Jaki jest powód nazwy „strona właścicielska”?
Strona będąca właścicielem relacji śledzonej przez Hibernate to strona relacji, która jest właścicielem klucza obcego w bazie danych.
Jaki problem rozwiązuje pojęcie posiadania strony?
Weźmy przykład dwóch obiektów zmapowanych bez deklarowania strony będącej właścicielem:
@Entity
@Table(name="PERSONS")
public class Person {
@OneToMany
private List<IdDocument> idDocuments;
}
@Entity
@Table(name="ID_DOCUMENTS")
public class IdDocument {
@ManyToOne
private Person person;
}
Z punktu widzenia obiektu obiektowego to odwzorowanie definiuje nie jedną relację dwukierunkową, ale dwie oddzielne relacje jednokierunkowe.
Mapowanie spowodowałoby nie tylko tabele PERSONS
i ID_DOCUMENTS
, ale także utworzyć trzecią tabelę skojarzeń PERSONS_ID_DOCUMENTS
:
CREATE TABLE PERSONS_ID_DOCUMENTS
(
persons_id bigint NOT NULL,
id_documents_id bigint NOT NULL,
CONSTRAINT fk_persons FOREIGN KEY (persons_id) REFERENCES persons (id),
CONSTRAINT fk_docs FOREIGN KEY (id_documents_id) REFERENCES id_documents (id),
CONSTRAINT pk UNIQUE (id_documents_id)
)
Zwróć uwagę tylko pk
na klucz podstawowy ID_DOCUMENTS
. W tym przypadku Hibernate śledzi obie strony relacji niezależnie: jeśli dodasz dokument do relacji Person.idDocuments
, wstawi on rekord do tabeli asocjacji PERSON_ID_DOCUMENTS
.
Z drugiej strony, jeśli wywołasz idDocument.setPerson(person)
, zmieniamy klucz obcy person_id w tabeli ID_DOCUMENTS
. Hibernate tworzy w bazie danych dwie relacje jednokierunkowe (klucz obcy) w celu zaimplementowania jednej dwukierunkowej relacji z obiektem.
Jak pojęcie strony właścicielskiej rozwiązuje problem:
Wiele razy to, czego chcemy, to tylko klucz obcy w tabeli w ID_DOCUMENTS
kierunku PERSONS
i dodatkowa tabela asocjacji.
Aby rozwiązać ten problem, musimy tak skonfigurować Hibernację, aby przestała śledzić modyfikacje relacji Person.idDocuments
. Hibernacja powinna śledzić tylko drugą stronę relacji IdDocument.person
i w tym celu dodajemy mappedBy :
@OneToMany(mappedBy="person")
private List<IdDocument> idDocuments;
Co to znaczy mappedBy?
Oznacza to coś takiego: „modyfikacje po tej stronie relacji są już odwzorowane przez
drugą stronę relacji IdDocument.person, więc nie ma potrzeby śledzenia ich tutaj oddzielnie w dodatkowej tabeli”.
Czy są jakieś GOTCHA, konsekwencje?
Korzystanie mappedBy , jeżeli tylko zadzwonić person.getDocuments().add(document)
, klucz obcy w ID_DOCUMENTS
będzie nie być związane z nowym dokumentem, ponieważ to nie jest będącym właścicielem / śledzone strona relacji!
Aby połączyć dokument z nową osobą, musisz jawnie wywołać document.setPerson(person)
, ponieważ jest to strona będąca właścicielem relacji.
Podczas korzystania z mappedBy deweloper jest odpowiedzialny za poznanie strony będącej właścicielem i zaktualizowanie właściwej strony relacji w celu wyzwolenia trwałości nowej relacji w bazie danych.