Ponieważ jest to bardzo częste pytanie, napisałem
ten artykuł , na którym opiera się ta odpowiedź.
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ędzy Post
jednostką nadrzędną a dzieckiem PostComment
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 z PostComment
jednostką podrzędną :
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "post_id")
private List<PostComment> comments = new ArrayList<>();
Dwukierunkowe powiązanie jeden do wielu
Jeśli używasz @OneToMany
z mappedBy
ustawionym atrybutem, masz dwukierunkowy stowarzyszenie. W naszym przypadku zarówno Post
jednostka ma kolekcję PostComment
jednostek potomnych, jak i PostComment
jednostka potomna ma odwołanie do Post
jednostki macierzystej , jak pokazano na poniższym diagramie:
W PostComment
jednostki, post
własność jednostka jest odwzorowany w sposób następujący:
@ManyToOne(fetch = FetchType.LAZY)
private Post post;
Powodem, dla którego jawnie ustawiliśmy ten fetch
atrybut, FetchType.LAZY
jest to, że domyślnie wszystkie @ManyToOne
i @OneToOne
skojarzenia są pobierane z niecierpliwością, co może powodować problemy z zapytaniami N + 1. Więcej informacji na ten temat można znaleźć w tym artykule .
W Post
encji comments
powiązanie jest mapowane w następujący sposób:
@OneToMany(
mappedBy = "post",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();
mappedBy
Atrybut z @OneToMany
odniesieniami adnotacji post
własności w dziecięcej PostComment
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
i removeChild
:
public void addComment(PostComment comment) {
comments.add(comment);
comment.setPost(this);
}
public void removeComment(PostComment comment) {
comments.remove(comment);
comment.setPost(null);
}
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.
Aby uzyskać więcej informacji na temat najlepszego sposobu synchronizowania skojarzeń dwukierunkowych z JPA i Hibernacją, zapoznaj się z tym artykułem .
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 .