Vì đây là một câu hỏi rất phổ biến, tôi đã viết
bài viết này , trên đó câu trả lời này dựa trên.
Hiệp hội một-nhiều-hướng
Như tôi đã giải thích trong bài viết này , nếu bạn sử dụng @OneToMany
chú thích với @JoinColumn
, thì bạn có một liên kết đơn hướng, giống như liên kết giữa Post
thực thể cha mẹ và con PostComment
trong sơ đồ sau:
Khi sử dụng liên kết một-nhiều-hướng, chỉ có phía cha mẹ ánh xạ liên kết.
Trong ví dụ này, chỉ có Post
thực thể sẽ xác định một @OneToMany
liên kết đến PostComment
thực thể con :
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "post_id")
private List<PostComment> comments = new ArrayList<>();
Hiệp hội một-nhiều-hai chiều
Nếu bạn sử dụng @OneToMany
với tập mappedBy
thuộc tính, bạn có một liên kết hai chiều. Trong trường hợp của chúng tôi, cả hai Post
thực thể đều có một tập hợp các PostComment
thực thể con và PostComment
thực thể con có một tham chiếu trở lại Post
thực thể cha , như được minh họa bằng sơ đồ sau:
Trong PostComment
thực thể, thuộc tính post
thực thể được ánh xạ như sau:
@ManyToOne(fetch = FetchType.LAZY)
private Post post;
Lý do chúng tôi đặt fetch
thuộc tính rõ ràng FetchType.LAZY
là vì theo mặc định, tất cả @ManyToOne
và các @OneToOne
liên kết được tìm nạp một cách háo hức, điều này có thể gây ra sự cố truy vấn N + 1. Để biết thêm chi tiết về chủ đề này, hãy xem bài viết này .
Trong Post
thực thể, comments
hiệp hội được ánh xạ như sau:
@OneToMany(
mappedBy = "post",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();
Các mappedBy
thuộc tính của @OneToMany
tài liệu tham khảo chú thích các post
tài sản ở trẻ em PostComment
tổ chức nào, và, theo cách này, Hibernate biết rằng sự liên kết hai chiều được điều khiển bởi các @ManyToOne
bên, trong đó có trách nhiệm quản lý các giá trị cột Ngoại chính mối quan hệ bảng này được dựa trên.
Đối với một hiệp hội hai chiều, bạn cũng cần có hai phương thức tiện ích, như addChild
và removeChild
:
public void addComment(PostComment comment) {
comments.add(comment);
comment.setPost(this);
}
public void removeComment(PostComment comment) {
comments.remove(comment);
comment.setPost(null);
}
Hai phương pháp này đảm bảo rằng cả hai mặt của hiệp hội hai chiều không đồng bộ. Không đồng bộ hóa cả hai đầu, Hibernate không đảm bảo rằng các thay đổi trạng thái kết hợp sẽ lan truyền đến cơ sở dữ liệu.
Để biết thêm chi tiết về wat tốt nhất để đồng bộ hóa các hiệp hội hai chiều với JPA và Hibernate, hãy xem bài viết này .
Chọn cái nào?
Các theo một hướng @OneToMany
liên kết không thực hiện rất tốt , vì vậy bạn nên tránh nó.
Bạn nên sử dụng hai chiều @OneToMany
sẽ hiệu quả hơn .