Dalam hal apa Anda menggunakan @JoinTable
anotasi JPA ?
Dalam hal apa Anda menggunakan @JoinTable
anotasi JPA ?
Jawaban:
EDIT 2017-04-29 : Seperti yang ditunjukkan oleh beberapa komentator, JoinTable
contohnya tidak memerlukan mappedBy
atribut anotasi. Bahkan, versi terbaru dari Hibernate menolak untuk memulai dengan mencetak kesalahan berikut:
org.hibernate.AnnotationException:
Associations marked as mappedBy must not define database mappings
like @JoinTable or @JoinColumn
Mari kita berpura-pura bahwa Anda memiliki entitas bernama Project
dan entitas lain bernama Task
dan setiap proyek dapat memiliki banyak tugas.
Anda bisa mendesain skema database untuk skenario ini dengan dua cara.
Solusi pertama adalah membuat tabel bernama Project
dan tabel lain bernama Task
dan menambahkan kolom kunci asing ke tabel tugas bernama project_id
:
Project Task
------- ----
id id
name name
project_id
Dengan cara ini, akan mungkin untuk menentukan proyek untuk setiap baris di tabel tugas. Jika Anda menggunakan pendekatan ini, di kelas entitas Anda, Anda tidak perlu tabel bergabung:
@Entity
public class Project {
@OneToMany(mappedBy = "project")
private Collection<Task> tasks;
}
@Entity
public class Task {
@ManyToOne
private Project project;
}
Solusi lain adalah dengan menggunakan tabel ketiga, misalnya Project_Tasks
, dan menyimpan hubungan antara proyek dan tugas dalam tabel itu:
Project Task Project_Tasks
------- ---- -------------
id id project_id
name name task_id
The Project_Tasks
tabel disebut "Join Table". Untuk mengimplementasikan solusi kedua ini di JPA Anda perlu menggunakan@JoinTable
anotasi. Misalnya, untuk menerapkan asosiasi satu-ke-satu yang uni-directional, kita dapat mendefinisikan entitas kita sebagai berikut:
Project
kesatuan:
@Entity
public class Project {
@Id
@GeneratedValue
private Long pid;
private String name;
@JoinTable
@OneToMany
private List<Task> tasks;
public Long getPid() {
return pid;
}
public void setPid(Long pid) {
this.pid = pid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Task> getTasks() {
return tasks;
}
public void setTasks(List<Task> tasks) {
this.tasks = tasks;
}
}
Task
kesatuan:
@Entity
public class Task {
@Id
@GeneratedValue
private Long tid;
private String name;
public Long getTid() {
return tid;
}
public void setTid(Long tid) {
this.tid = tid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Ini akan membuat struktur database berikut:
The @JoinTable
penjelasan juga memungkinkan Anda menyesuaikan berbagai aspek tabel bergabung. Misalnya, sudahkah kami memberi anotasi pada tasks
properti seperti ini:
@JoinTable(
name = "MY_JT",
joinColumns = @JoinColumn(
name = "PROJ_ID",
referencedColumnName = "PID"
),
inverseJoinColumns = @JoinColumn(
name = "TASK_ID",
referencedColumnName = "TID"
)
)
@OneToMany
private List<Task> tasks;
Database yang dihasilkan akan menjadi:
Akhirnya, jika Anda ingin membuat skema untuk asosiasi banyak-ke-banyak, menggunakan tabel bergabung adalah satu-satunya solusi yang tersedia.
@JoinTable/@JoinColumn
dapat dijelaskan pada bidang yang sama dengan mappedBy
. Jadi contoh yang benar harus menjaga mappedBy
di Project
, dan memindahkan @JoinColumn
ke Task.project
(atau sebaliknya)
Project_Tasks
membutuhkan name
dari Task
juga, yang menjadi tiga kolom: project_id
, task_id
, task_name
, bagaimana untuk mencapai hal ini?
Caused by: org.hibernate.AnnotationException: Associations marked as mappedBy must not define database mappings like @JoinTable or @JoinColumn:
Juga lebih bersih untuk digunakan @JoinTable
ketika Entitas dapat menjadi anak dalam beberapa hubungan orang tua / anak dengan berbagai jenis orang tua. Untuk menindaklanjuti dengan contoh Behrang, bayangkan Tugas dapat menjadi anak dari Proyek, Orang, Departemen, Studi, dan Proses.
Haruskah task
tabel memiliki 5 nullable
bidang kunci asing? Saya pikir tidak...
Ini satu-satunya solusi untuk memetakan asosiasi ManyToMany: Anda memerlukan tabel gabungan antara tabel dua entitas untuk memetakan asosiasi.
Ini juga digunakan untuk asosiasi OneToMany (biasanya searah) ketika Anda tidak ingin menambahkan kunci asing di tabel banyak sisi dan dengan demikian tetap independen dari satu sisi.
Cari @JoinTable di dokumentasi hibernate untuk penjelasan dan contoh.
Ini memungkinkan Anda menangani hubungan Many to Many. Contoh:
Table 1: post
post has following columns
____________________
| ID | DATE |
|_________|_________|
| | |
|_________|_________|
Table 2: user
user has the following columns:
____________________
| ID |NAME |
|_________|_________|
| | |
|_________|_________|
Bergabung dengan Tabel memungkinkan Anda membuat pemetaan menggunakan:
@JoinTable(
name="USER_POST",
joinColumns=@JoinColumn(name="USER_ID", referencedColumnName="ID"),
inverseJoinColumns=@JoinColumn(name="POST_ID", referencedColumnName="ID"))
akan membuat tabel:
____________________
| USER_ID| POST_ID |
|_________|_________|
| | |
|_________|_________|
@ManyToMany
asosiasiPaling sering, Anda harus menggunakan @JoinTable
anotasi untuk menentukan pemetaan hubungan tabel banyak-ke-banyak:
Jadi, anggap Anda memiliki tabel database berikut:
Di Post
entitas, Anda akan memetakan hubungan ini, seperti ini:
@ManyToMany(cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
@JoinTable(
name = "post_tag",
joinColumns = @JoinColumn(name = "post_id"),
inverseJoinColumns = @JoinColumn(name = "tag_id")
)
private List<Tag> tags = new ArrayList<>();
The @JoinTable
penjelasan digunakan untuk menentukan nama tabel melaluiname
atribut, serta kolom Foreign Key yang referensi yang post
tabel (misalnya, joinColumns
) dan kolom Foreign Key di post_tag
tabel link yang referensi yang Tag
entitas melalui inverseJoinColumns
atribut.
Perhatikan bahwa atribut kaskade
@ManyToMany
anotasi diatur kePERSIST
danMERGE
hanya karenaREMOVE
adalah ide yang buruk karena kita pernyataan DELETE akan dikeluarkan untuk catatan induk lainnya,tag
dalam kasus kami, bukan kepost_tag
catatan. Untuk detail lebih lanjut tentang topik ini, lihat artikel ini .
@OneToMany
Asosiasi searah@OneToMany
Asosiasi searah , yang kurang a@JoinColumn
pemetaan, berperilaku seperti hubungan tabel banyak-ke-banyak, bukan satu-ke-banyak.
Jadi, dengan asumsi Anda memiliki pemetaan entitas berikut:
@Entity(name = "Post")
@Table(name = "post")
public class Post {
@Id
@GeneratedValue
private Long id;
private String title;
@OneToMany(
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();
//Constructors, getters and setters removed for brevity
}
@Entity(name = "PostComment")
@Table(name = "post_comment")
public class PostComment {
@Id
@GeneratedValue
private Long id;
private String review;
//Constructors, getters and setters removed for brevity
}
Hibernate akan mengasumsikan skema database berikut untuk pemetaan entitas di atas:
Seperti yang sudah dijelaskan, @OneToMany
pemetaan JPA searah berperilaku seperti asosiasi banyak-ke-banyak.
Untuk menyesuaikan tabel tautan, Anda juga dapat menggunakan @JoinTable
anotasi:
@OneToMany(
cascade = CascadeType.ALL,
orphanRemoval = true
)
@JoinTable(
name = "post_comment_ref",
joinColumns = @JoinColumn(name = "post_id"),
inverseJoinColumns = @JoinColumn(name = "post_comment_id")
)
private List<PostComment> comments = new ArrayList<>();
Dan sekarang, tabel tautan akan dipanggil post_comment_ref
dan kolom Kunci Asing akan post_id
, untuk post
tabel, dan post_comment_id
, untukpost_comment
tabel.
@OneToMany
Asosiasi searah tidak efisien, jadi Anda lebih baik menggunakan@OneToMany
asosiasi dua arah atau hanya@ManyToOne
sisi. Lihat artikel ini untuk detail lebih lanjut tentang topik ini.