Ini adalah pertanyaan yang sangat umum, jadi jawaban ini didasarkan pada artikel yang saya tulis di blog saya.
Satu-ke-banyak
Hubungan tabel satu-ke-banyak terlihat sebagai berikut:

Dalam sistem database relasional, hubungan tabel satu-ke-banyak menghubungkan dua tabel berdasarkan Foreign Keykolom pada anak yang merujuk pada Primary Keybaris tabel induk.
Dalam diagram tabel di atas, post_idkolom dalam post_commenttabel memiliki Foreign Keyhubungan dengan kolom postid tabel Primary Key:
ALTER TABLE
post_comment
ADD CONSTRAINT
fk_post_comment_post_id
FOREIGN KEY (post_id) REFERENCES post
@ManyToOne penjelasan
Cara terbaik untuk memetakan hubungan tabel satu-ke-banyak adalah dengan menggunakan @ManyToOneanotasi.
Dalam kasus kami, entitas anak, PostCommentmemetakan post_idkolom Kunci Asing menggunakan @ManyToOneanotasi:
@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;
}
Menggunakan @OneToManyanotasi JPA
Hanya karena Anda memiliki opsi untuk menggunakan @OneToManyanotasi, itu tidak berarti ini harus menjadi opsi default untuk setiap hubungan database satu-ke-banyak . Masalah dengan koleksi adalah bahwa kita hanya bisa menggunakannya ketika jumlah catatan anak agak terbatas.
Cara terbaik untuk memetakan @OneToManyasosiasi adalah dengan mengandalkan @ManyToOnesisi untuk menyebarkan semua perubahan status entitas:
@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);
}
}
Entitas induk Post,, menampilkan dua metode utilitas (misalnya addCommentdan removeComment) yang digunakan untuk menyinkronkan kedua sisi dari asosiasi dua arah. Anda harus selalu memberikan metode ini setiap kali Anda bekerja dengan asosiasi dua arah karena, jika tidak, Anda berisiko mengalami masalah propagasi negara yang sangat halus .
@OneToManyAsosiasi searah harus dihindari karena kurang efisien daripada menggunakan @ManyToOneatau @OneToManyasosiasi dua arah .
Untuk detail lebih lanjut tentang cara terbaik untuk memetakan @OneToManyhubungan dengan JPA dan Hibernate, lihat artikel ini .
Satu-ke-satu
Hubungan tabel satu-ke-satu terlihat sebagai berikut:

Dalam sistem basis data relasional, hubungan tabel satu-ke-satu menghubungkan dua tabel berdasarkan Primary Keykolom pada anak yang juga merupakan Foreign Keyreferensi Primary Keydari baris tabel induk.
Oleh karena itu, kita dapat mengatakan bahwa tabel anak berbagi Primary Keydengan tabel induk.
Dalam diagram tabel di atas, idkolom dalam post_detailstabel juga memiliki Foreign Keyhubungan dengan kolom posttabel id Primary Key:
ALTER TABLE
post_details
ADD CONSTRAINT
fk_post_details_id
FOREIGN KEY (id) REFERENCES post
Menggunakan JPA @OneToOnedengan @MapsIdanotasi
Cara terbaik untuk memetakan @OneToOnehubungan adalah menggunakan @MapsId. Dengan cara ini, Anda bahkan tidak memerlukan asosiasi dua arah karena Anda selalu dapat mengambil PostDetailsentitas dengan menggunakan Postpengidentifikasi entitas.
Pemetaannya terlihat seperti ini:
[kode bahasa = "java"] @Entity (name = "PostDetails") @Table (name = "post_details") kelas publik 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
} [/ kode]
Dengan cara ini, idproperti berfungsi sebagai Primary Key dan Foreign Key. Anda akan melihat bahwa @Idkolom tidak lagi menggunakan @GeneratedValueanotasi karena pengenal diisi dengan pengidentifikasi postasosiasi.
Untuk detail lebih lanjut tentang cara terbaik untuk memetakan @OneToOnehubungan dengan JPA dan Hibernate, lihat artikel ini .
Banyak ke banyak
Hubungan tabel banyak-ke-banyak terlihat sebagai berikut:

Dalam sistem basis data relasional, hubungan banyak-ke-banyak tabel menghubungkan dua tabel induk melalui tabel anak yang berisi dua Foreign Keykolom referensi Primary Keykolom dari dua tabel induk.
Dalam diagram tabel di atas, post_idkolom dalam post_tagtabel juga memiliki Foreign Keyhubungan dengan kolom postid tabel Primary Key:
ALTER TABLE
post_tag
ADD CONSTRAINT
fk_post_tag_post_id
FOREIGN KEY (post_id) REFERENCES post
Dan, tag_idkolom dalam post_tagtabel memiliki Foreign Keyhubungan dengan kolom tagid tabel Primary Key:
ALTER TABLE
post_tag
ADD CONSTRAINT
fk_post_tag_tag_id
FOREIGN KEY (tag_id) REFERENCES tag
Menggunakan @ManyToManypemetaan JPA
Ini adalah bagaimana Anda bisa memetakan many-to-manyhubungan tabel dengan JPA dan 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);
}
}
- The
tagsasosiasi dalam Postentitas hanya mendefinisikan PERSISTdan MERGEkaskade jenis. Seperti dijelaskan dalam artikel ini , REMOVE transisi status entitas tidak masuk akal untuk @ManyToManyasosiasi JPA karena hal itu dapat memicu penghapusan berantai yang pada akhirnya akan menghapus kedua sisi asosiasi.
- Sebagaimana dijelaskan dalam artikel ini , metode tambah / hapus utilitas wajib jika Anda menggunakan asosiasi dua arah sehingga Anda dapat memastikan bahwa kedua sisi asosiasi tersebut sinkron.
- The
Postentitas menggunakan entitas pengidentifikasi untuk kesetaraan karena tidak memiliki tombol apa saja bisnis yang unik. Seperti yang dijelaskan dalam artikel ini , Anda dapat menggunakan pengidentifikasi entitas untuk kesetaraan selama Anda memastikan bahwa itu tetap konsisten di semua transisi status entitas .
- The
Tagentitas memiliki kunci bisnis yang unik yang ditandai dengan Hibernate spesifik @NaturalIdpenjelasan. Ketika itu masalahnya, kunci bisnis yang unik adalah kandidat terbaik untuk pemeriksaan kesetaraan .
- The
mappedByatribut dari postsasosiasi dalam Tagtanda entitas yang, dalam hubungan dua arah ini, Postentitas memiliki asosiasi. Ini diperlukan karena hanya satu sisi yang dapat memiliki hubungan, dan perubahan hanya disebarkan ke database dari sisi tertentu ini.
- Ini
Setlebih disukai, karena menggunakan Listdengan @ManyToManykurang efisien.
Untuk detail lebih lanjut tentang cara terbaik untuk memetakan @ManyToManyhubungan dengan JPA dan Hibernate, lihat artikel ini .