Đây là một câu hỏi rất phổ biến, vì vậy câu trả lời này dựa trên bài viết này tôi đã viết trên blog của mình.
Một-nhiều
Mối quan hệ một-nhiều bảng trông như sau:

Trong một hệ thống cơ sở dữ liệu quan hệ, mối quan hệ một-nhiều bảng liên kết hai bảng dựa trên một Foreign Keycột trong con tham chiếu đến hàng Primary Keycủa bảng cha.
Trong sơ đồ bảng ở trên, post_idcột trong post_commentbảng có Foreign Keymối quan hệ với cột postid bảng Primary Key:
ALTER TABLE
post_comment
ADD CONSTRAINT
fk_post_comment_post_id
FOREIGN KEY (post_id) REFERENCES post
Chú thích @ManyToOne
Cách tốt nhất để ánh xạ mối quan hệ một-nhiều bảng là sử dụng @ManyToOnechú thích.
Trong trường hợp của chúng tôi, thực thể con, PostCommentánh xạ post_idcột Khóa ngoài bằng cách sử dụng @ManyToOnechú thích:
@Entity(name = "PostComment")
@Table(name = "post_comment")
public class PostComment {
@Id
@GeneratedValue
private Long id;
private String review;
@ManyToOne(fetch = FetchType.LAZY)
private Post post;
}
Sử dụng @OneToManychú thích JPA
Chỉ vì bạn có tùy chọn sử dụng @OneToManychú thích, điều đó không có nghĩa đây sẽ là tùy chọn mặc định cho mỗi một-nhiều mối quan hệ cơ sở dữ liệu . Vấn đề với các bộ sưu tập là chúng tôi chỉ có thể sử dụng chúng khi số lượng hồ sơ con khá hạn chế.
Cách tốt nhất để lập bản đồ @OneToManyliên kết là dựa vào một @ManyToOnebên để tuyên truyền tất cả các thay đổi trạng thái thực thể:
@Entity(name = "Post")
@Table(name = "post")
public class Post {
@Id
@GeneratedValue
private Long id;
private String title;
@OneToMany(
mappedBy = "post",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();
//Constructors, getters and setters removed for brevity
public void addComment(PostComment comment) {
comments.add(comment);
comment.setPost(this);
}
public void removeComment(PostComment comment) {
comments.remove(comment);
comment.setPost(null);
}
}
Thực thể mẹ Post, có hai phương thức tiện ích (ví dụ addCommentvà removeComment) được sử dụng để đồng bộ hóa cả hai mặt của liên kết hai chiều. Bạn nên luôn luôn cung cấp các phương thức này bất cứ khi nào bạn làm việc với một hiệp hội hai chiều vì nếu không, bạn có nguy cơ gặp phải các vấn đề lan truyền trạng thái rất tinh tế .
Nên @OneToManytránh liên kết đơn hướng vì nó kém hiệu quả hơn so với sử dụng @ManyToOnehoặc @OneToManyliên kết hai chiều .
Để biết thêm chi tiết về cách tốt nhất để lập bản đồ @OneToManymối quan hệ với JPA và Hibernate, hãy xem bài viết này .
Một chọi một
Mối quan hệ một-một-bảng trông như sau:

Trong một hệ thống cơ sở dữ liệu quan hệ, mối quan hệ một-một liên kết hai bảng dựa trên một Primary Keycột trong con cũng là Foreign Keytham chiếu Primary Keycủa hàng của bảng cha.
Do đó, chúng ta có thể nói rằng bảng con chia sẻ Primary Keyvới bảng cha.
Trong sơ đồ bảng trên, idcột trong post_detailsbảng cũng có Foreign Keymối quan hệ với cột postbảng id Primary Key:
ALTER TABLE
post_details
ADD CONSTRAINT
fk_post_details_id
FOREIGN KEY (id) REFERENCES post
Sử dụng JPA @OneToOnevới @MapsIdcác chú thích
Cách tốt nhất để lập bản đồ @OneToOnemối quan hệ là sử dụng @MapsId. Theo cách này, bạn thậm chí không cần liên kết hai chiều vì bạn luôn có thể tìm nạp PostDetailsthực thể bằng cách sử dụng Postđịnh danh thực thể.
Ánh xạ trông như thế này:
[code ngôn ngữ = "java"] @Entity (name = "PostDetails") @Table (name = "post_details") lớp công khai PostDetails {
@Id
private Long id;
@Column(name = "created_on")
private Date createdOn;
@Column(name = "created_by")
private String createdBy;
@OneToOne(fetch = FetchType.LAZY)
@MapsId
@JoinColumn(name = "id")
private Post post;
public PostDetails() {}
public PostDetails(String createdBy) {
createdOn = new Date();
this.createdBy = createdBy;
}
//Getters and setters omitted for brevity
} [/ mã]
Bằng cách này, idtài sản đóng vai trò là Khóa chính và Khóa ngoại. Bạn sẽ nhận thấy rằng @Idcột không còn sử dụng @GeneratedValuechú thích vì mã định danh được điền với mã định danh của postliên kết.
Để biết thêm chi tiết về cách tốt nhất để lập bản đồ @OneToOnemối quan hệ với JPA và Hibernate, hãy xem bài viết này .
Nhiều nhiều
Mối quan hệ nhiều-nhiều-bảng trông như sau:

Trong một hệ thống cơ sở dữ liệu quan hệ, mối quan hệ nhiều-nhiều bảng liên kết hai bảng cha thông qua một bảng con chứa hai Foreign Keycột tham chiếu các Primary Keycột của hai bảng cha.
Trong sơ đồ bảng ở trên, post_idcột trong post_tagbảng cũng có Foreign Keymối quan hệ với cột postid bảng Primary Key:
ALTER TABLE
post_tag
ADD CONSTRAINT
fk_post_tag_post_id
FOREIGN KEY (post_id) REFERENCES post
Và, tag_idcột trong post_tagbảng có Foreign Keymối quan hệ với cột tagid bảng Primary Key:
ALTER TABLE
post_tag
ADD CONSTRAINT
fk_post_tag_tag_id
FOREIGN KEY (tag_id) REFERENCES tag
Sử dụng @ManyToManyánh xạ JPA
Đây là cách bạn có thể ánh xạ many-to-manymối quan hệ bảng với JPA và Hibernate:
@Entity(name = "Post")
@Table(name = "post")
public class Post {
@Id
@GeneratedValue
private Long id;
private String title;
@ManyToMany(cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
@JoinTable(name = "post_tag",
joinColumns = @JoinColumn(name = "post_id"),
inverseJoinColumns = @JoinColumn(name = "tag_id")
)
private Set<Tag> tags = new HashSet<>();
//Getters and setters ommitted for brevity
public void addTag(Tag tag) {
tags.add(tag);
tag.getPosts().add(this);
}
public void removeTag(Tag tag) {
tags.remove(tag);
tag.getPosts().remove(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Post)) return false;
return id != null && id.equals(((Post) o).getId());
}
@Override
public int hashCode() {
return 31;
}
}
@Entity(name = "Tag")
@Table(name = "tag")
public class Tag {
@Id
@GeneratedValue
private Long id;
@NaturalId
private String name;
@ManyToMany(mappedBy = "tags")
private Set<Post> posts = new HashSet<>();
//Getters and setters ommitted for brevity
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Tag tag = (Tag) o;
return Objects.equals(name, tag.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}
- Liên
tagskết trong Postthực thể chỉ định nghĩa các loại PERSISTvà MERGEtầng. Như đã giải thích trong bài viết này , REMOVE quá trình chuyển đổi trạng thái thực thể không có ý nghĩa gì đối với một @ManyToManyhiệp hội JPA vì nó có thể kích hoạt việc xóa chuỗi mà cuối cùng sẽ xóa sạch cả hai mặt của hiệp hội.
- Như đã giải thích trong bài viết này , các phương thức tiện ích thêm / xóa là bắt buộc nếu bạn sử dụng các liên kết hai chiều để bạn có thể đảm bảo rằng cả hai mặt của liên kết đều đồng bộ.
- Thực
Postthể sử dụng định danh thực thể cho sự bình đẳng vì nó không có bất kỳ khóa kinh doanh duy nhất nào. Như đã giải thích trong bài viết này , bạn có thể sử dụng định danh thực thể cho sự bình đẳng miễn là bạn đảm bảo rằng nó vẫn nhất quán trong tất cả các chuyển đổi trạng thái thực thể .
- Thực
Tagthể có khóa doanh nghiệp duy nhất được đánh dấu bằng @NaturalIdchú thích dành riêng cho Hibernate . Khi đó, khóa kinh doanh duy nhất là ứng cử viên tốt nhất để kiểm tra bình đẳng .
- Các
mappedBythuộc tính của postshiệp hội trong Tagdấu ngoặc đơn vị rằng, trong mối quan hệ hai chiều này, các Postđơn vị sở hữu hiệp hội. Điều này là cần thiết vì chỉ một bên có thể sở hữu một mối quan hệ và các thay đổi chỉ được truyền đến cơ sở dữ liệu từ phía cụ thể này.
- Điều
Setnày được ưu tiên, vì sử dụng một Listvới @ManyToManyít hiệu quả hơn.
Để biết thêm chi tiết về cách tốt nhất để lập bản đồ @ManyToManymối quan hệ với JPA và Hibernate, hãy xem bài viết này .