นี่เป็นคำถามที่พบบ่อยมากดังนั้นคำตอบนี้เป็นไปตามบทความที่ฉันเขียนในบล็อกของฉัน
หนึ่งต่อหลายคน
ความสัมพันธ์ของตารางแบบหนึ่งต่อกลุ่มมีลักษณะดังนี้:
ในระบบฐานข้อมูลเชิงสัมพันธ์ความสัมพันธ์แบบหนึ่งต่อหลายตารางจะเชื่อมโยงสองตารางตาม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
ความสัมพันธ์กับคอลัมน์tag
id ของตาราง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 ตรวจสอบบทความนี้