นี่เป็นคำถามที่พบบ่อยมากดังนั้นคำตอบนี้เป็นไปตามบทความที่ฉันเขียนในบล็อกของฉัน
หนึ่งต่อหลายคน
ความสัมพันธ์ของตารางแบบหนึ่งต่อกลุ่มมีลักษณะดังนี้:

ในระบบฐานข้อมูลเชิงสัมพันธ์ความสัมพันธ์แบบหนึ่งต่อหลายตารางจะเชื่อมโยงสองตารางตามForeign Keyคอลัมน์ในคอลัมน์ย่อยที่อ้างอิงถึงPrimary Keyแถวของตารางหลัก
ในแผนภาพตารางด้านบนpost_idคอลัมน์ในpost_commentตารางมีForeign Keyความสัมพันธ์กับคอลัมน์postรหัสตารางPrimary Key:
ALTER TABLE
post_comment
ADD CONSTRAINT
fk_post_comment_post_id
FOREIGN KEY (post_id) REFERENCES post
@ManyToOne คำอธิบายประกอบ
วิธีที่ดีที่สุดในการแมปความสัมพันธ์ของตารางหนึ่งต่อหลายคือการใช้ @ManyToOneคำอธิบายประกอบ
ในกรณีของเราเอนทิตีสำหรับเด็กPostCommentแม็พpost_idคอลัมน์ Foreign Key โดยใช้@ManyToOneหมายเหตุประกอบ:
@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;
}
ใช้ JPA @OneToManyคำอธิบายประกอบ
เพียงเพราะคุณมีตัวเลือกในการใช้@OneToManyคำอธิบายประกอบมันไม่ได้หมายความว่านี่ควรเป็นตัวเลือกเริ่มต้นสำหรับทุกๆ คนความสัมพันธ์ฐานข้อมูลปัญหาเกี่ยวกับคอลเลกชันคือเราสามารถใช้งานได้ก็ต่อเมื่อจำนวนเรคคอร์ดย่อยมี จำกัด
วิธีที่ดีที่สุดในการแมปการ@OneToManyเชื่อมโยงคือการพึ่งพา@ManyToOneด้านข้างเพื่อเผยแพร่การเปลี่ยนแปลงสถานะของเอนทิตีทั้งหมด:
@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);
}
}
หน่วยงานหลักPost, มีคุณสมบัติสองวิธีการยูทิลิตี้ (เช่นaddCommentและremoveComment) ซึ่งจะใช้ในการประสานทั้งสองด้านของการเชื่อมโยงแบบสองทิศทาง คุณควรให้วิธีการเหล่านี้ทุกครั้งที่คุณทำงานกับสมาคมแบบสองทิศทางในทางอื่น ๆ มิฉะนั้นคุณก็เสี่ยงต่อการแพร่กระจายของปัญหาที่ละเอียดอ่อนมากประเด็นการขยายพันธุ์ของรัฐที่ลึกซึ้งมาก
@OneToManyควรหลีกเลี่ยงการเชื่อมโยงทิศทางเดียวเนื่องจากมีประสิทธิภาพน้อยกว่าการใช้@ManyToOneหรือการ@OneToManyเชื่อมโยงแบบสองทิศทาง
สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับวิธีที่ดีที่สุดในการทำแผนที่@OneToManyความสัมพันธ์กับ JPA และ Hibernate ตรวจสอบบทความนี้
หนึ่งต่อหนึ่ง
ความสัมพันธ์ของตารางแบบหนึ่งต่อหนึ่งมีลักษณะดังนี้:

ในระบบฐานข้อมูลเชิงสัมพันธ์ความสัมพันธ์แบบหนึ่งต่อหนึ่งเชื่อมโยงตารางสองตารางโดยยึดตามPrimary Keyคอลัมน์ในคอลัมน์ย่อยซึ่งเป็นการForeign Keyอ้างอิงPrimary Keyแถวของตารางแม่แถวด้วย
ดังนั้นเราสามารถพูดได้ว่าตารางลูกใช้Primary Keyร่วมกับตารางหลัก
ในแผนภาพตารางด้านบนidคอลัมน์ในpost_detailsตารางมีForeign Keyความสัมพันธ์กับคอลัมน์postตารางด้วยid Primary Key:
ALTER TABLE
post_details
ADD CONSTRAINT
fk_post_details_id
FOREIGN KEY (id) REFERENCES post
การใช้ JPA @OneToOneพร้อม@MapsIdหมายเหตุประกอบ
วิธีที่ดีที่สุดแมสัมพันธ์กับการใช้งาน@OneToOne @MapsIdด้วยวิธีนี้คุณไม่จำเป็นต้องมีการเชื่อมโยงแบบสองทิศทางเนื่องจากคุณสามารถดึงPostDetailsเอนทิตีได้เสมอโดยใช้Postตัวระบุเอนทิตี
การทำแผนที่มีลักษณะดังนี้:
[code language = "java"] @Entity (name = "PostDetails") @Table (name = "post_details") คลาสสาธารณะ 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
} [/ รหัส]
วิธีนี้idคุณสมบัติทำหน้าที่เป็นทั้งคีย์หลักและคีย์ต่างประเทศ คุณจะสังเกตเห็นว่า@Idคอลัมน์ไม่ได้ใช้@GeneratedValueคำอธิบายประกอบอีกต่อไปเนื่องจากตัวระบุนั้นบรรจุด้วยตัวระบุของการpostเชื่อมโยง
สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับวิธีที่ดีที่สุดในการทำแผนที่@OneToOneความสัมพันธ์กับ JPA และ Hibernate ตรวจสอบบทความนี้
หลายต่อหลายคน
ความสัมพันธ์ของตารางแบบหลายต่อกลุ่มมีลักษณะดังนี้:

ในระบบฐานข้อมูลเชิงสัมพันธ์ความสัมพันธ์แบบหลายต่อหลายตารางจะเชื่อมโยงสองตารางหลักผ่านตารางลูกซึ่งมีสองForeign Keyคอลัมน์ที่อ้างอิงถึงPrimary Keyคอลัมน์ของตารางหลักสองตาราง
ในแผนภาพตารางด้านบนpost_idคอลัมน์ในpost_tagตารางมีForeign Keyความสัมพันธ์กับคอลัมน์postรหัสตารางด้วยPrimary Key:
ALTER TABLE
post_tag
ADD CONSTRAINT
fk_post_tag_post_id
FOREIGN KEY (post_id) REFERENCES post
และtag_idคอลัมน์ในpost_tagตารางมีForeign Keyความสัมพันธ์กับคอลัมน์tagid ของตารางPrimary Key:
ALTER TABLE
post_tag
ADD CONSTRAINT
fk_post_tag_tag_id
FOREIGN KEY (tag_id) REFERENCES tag
การใช้การ@ManyToManyแม็พJPA
นี่คือวิธีที่คุณสามารถแมปmany-to-manyความสัมพันธ์ของตารางกับ JPA และไฮเบอร์เนต:
@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);
}
}
- การ
tagsเชื่อมโยงในPostเอนทิตีกำหนดประเภทPERSISTและMERGEเรียงซ้อนเท่านั้น ตามที่อธิบายไว้ในบทความนี้การREMOVE เปลี่ยนสถานะนิติบุคคลไม่สมเหตุสมผลสำหรับการ@ManyToManyเชื่อมโยง JPA เนื่องจากอาจทำให้เกิดการลบการเชื่อมโยงที่จะล้างทั้งสองด้านของการเชื่อมโยงในท้ายที่สุด
- ตามที่อธิบายไว้ใน บทความนี้วิธีการเพิ่ม / ลบยูทิลิตี้เป็นสิ่งจำเป็นถ้าคุณใช้การเชื่อมโยงแบบสองทิศทางเพื่อให้คุณสามารถตรวจสอบให้แน่ใจว่าทั้งสองด้านของการเชื่อมโยงมีการซิงค์
Postนิติบุคคลใช้ระบุกิจการเพื่อความเท่าเทียมกันเพราะมันขาดที่สำคัญทางธุรกิจใด ๆ ที่ไม่ซ้ำกัน ตามที่อธิบายไว้ในบทความนี้คุณสามารถใช้ตัวระบุเอนทิตีเพื่อความเท่าเทียมกันตราบเท่าที่คุณตรวจสอบให้แน่ใจว่ามันยังคงสอดคล้องกันในการเปลี่ยนสถานะของนิติบุคคลทั้งหมดการเปลี่ยนสถานะนิติบุคคล
Tagนิติบุคคลที่มีคีย์ธุรกิจที่ไม่ซ้ำกันซึ่งมีการทำเครื่องหมายกับ Hibernate เฉพาะ@NaturalIdคำอธิบายประกอบ เมื่อเป็นเช่นนั้นกุญแจธุรกิจที่เป็นเอกลักษณ์ก็คือผู้สมัครที่ดีที่สุดสำหรับการตรวจสอบความเท่าเทียมกัน
mappedByแอตทริบิวต์ของpostsสมาคมในTagเครื่องหมายนิติบุคคลที่ในความสัมพันธ์แบบสองทิศทางนี้Postนิติบุคคลเป็นเจ้าของสมาคม สิ่งนี้จำเป็นเนื่องจากมีเพียงด้านเดียวเท่านั้นที่สามารถเป็นเจ้าของความสัมพันธ์ได้และการเปลี่ยนแปลงจะแพร่กระจายไปยังฐานข้อมูลจากด้านเฉพาะนี้เท่านั้น
Setคือการเป็นที่ต้องการเช่นใช้Listกับ@ManyToManyมีประสิทธิภาพน้อย
สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับวิธีที่ดีที่สุดในการทำแผนที่@ManyToManyความสัมพันธ์กับ JPA และ Hibernate ตรวจสอบบทความนี้