เหตุใดความคิดเกี่ยวกับความเป็นเจ้าของจึงจำเป็น:
แนวความคิดเกี่ยวกับความเป็นเจ้าของของความสัมพันธ์แบบสองทิศทางนั้นมาจากข้อเท็จจริงที่ว่าในฐานข้อมูลเชิงสัมพันธ์ไม่มีความสัมพันธ์แบบสองทิศทางเหมือนในกรณีของวัตถุ ในฐานข้อมูลเรามีเพียงความสัมพันธ์แบบทิศทางเดียว - คีย์ต่างประเทศ
สาเหตุของชื่อ 'ฝั่งเจ้าของ' คืออะไร?
ด้านการเป็นเจ้าของของความสัมพันธ์ที่ติดตามโดย Hibernate คือด้านของความสัมพันธ์ที่เป็นเจ้าของคีย์ต่างประเทศในฐานข้อมูล
อะไรคือปัญหาที่ความคิดเกี่ยวกับการเป็นเจ้าของสามารถแก้ไขได้?
ยกตัวอย่างเอนทิตีสองรายการที่แมปโดยไม่ประกาศฝั่งเจ้าของ:
@Entity
@Table(name="PERSONS")
public class Person {
@OneToMany
private List<IdDocument> idDocuments;
}
@Entity
@Table(name="ID_DOCUMENTS")
public class IdDocument {
@ManyToOne
private Person person;
}
จากมุมมอง OO การทำแผนที่นี้ไม่ได้กำหนดความสัมพันธ์แบบสองทิศทาง แต่เป็นสองทิศทางทิศทางที่แยกจากกัน
การแมปจะไม่เพียงสร้างตารางPERSONS
และID_DOCUMENTS
ยังสร้างตารางการเชื่อมโยงที่สามด้วยPERSONS_ID_DOCUMENTS
:
CREATE TABLE PERSONS_ID_DOCUMENTS
(
persons_id bigint NOT NULL,
id_documents_id bigint NOT NULL,
CONSTRAINT fk_persons FOREIGN KEY (persons_id) REFERENCES persons (id),
CONSTRAINT fk_docs FOREIGN KEY (id_documents_id) REFERENCES id_documents (id),
CONSTRAINT pk UNIQUE (id_documents_id)
)
ขอให้สังเกตคีย์หลักpk
ในID_DOCUMENTS
เท่านั้น ในกรณีนี้ไฮเบอร์เนตติดตามทั้งสองด้านของความสัมพันธ์โดยอิสระ: หากคุณเพิ่มเอกสารลงในความสัมพันธ์เอกสารPerson.idDocuments
นั้นจะแทรกระเบียนในตารางการเชื่อมโยงPERSON_ID_DOCUMENTS
มันแทรกบันทึกในตารางสมาคม
ในทางกลับกันถ้าเราโทรหาidDocument.setPerson(person)
เราเปลี่ยนที่สำคัญต่างประเทศ person_id ID_DOCUMENTS
บนโต๊ะ ไฮเบอร์เนตกำลังสร้างความสัมพันธ์สองทิศทางเดียว (คีย์ต่างประเทศ) บนฐานข้อมูลเพื่อใช้งานอย่างใดอย่างหนึ่งความสัมพันธ์วัตถุแบบสองทิศทาง
แนวคิดเรื่องการเป็นเจ้าของช่วยแก้ปัญหาได้อย่างไร:
หลายครั้งสิ่งที่เราต้องการเป็นเพียงที่สำคัญต่างประเทศในตารางID_DOCUMENTS
ต่อPERSONS
และตารางการเชื่อมโยงพิเศษ
เพื่อแก้ปัญหานี้เราจำเป็นต้องกำหนดค่า Hibernate Person.idDocuments
เพื่อหยุดการติดตามการปรับเปลี่ยนความสัมพันธ์ ไฮเบอร์เนตควรติดตามอีกด้านหนึ่งของความสัมพันธ์IdDocument.person
เท่านั้นและในการทำเช่นนั้นเราจึงเพิ่มmappedBy :
@OneToMany(mappedBy="person")
private List<IdDocument> idDocuments;
mappedBy หมายถึงอะไร?
ซึ่งหมายความว่า: "การแก้ไขในด้านนี้ของความสัมพันธ์ถูกแมปไว้แล้วโดย
อีกด้านหนึ่งของความสัมพันธ์ IdDocument.person ดังนั้นไม่จำเป็นต้องติดตามที่นี่แยกต่างหากในตารางพิเศษ"
มี GOTCHA ผลที่ตามมาหรือไม่?
การใช้mappedByหากเราเรียกเท่านั้นperson.getDocuments().add(document)
Foreign Key ในID_DOCUMENTS
จะไม่ถูกเชื่อมโยงกับเอกสารใหม่เพราะนี่ไม่ใช่ด้านการเป็นเจ้าของ / ติดตามของความสัมพันธ์!
ในการเชื่อมโยงเอกสารกับบุคคลใหม่คุณต้องโทรอย่างชัดเจนdocument.setPerson(person)
เพราะนั่นคือฝั่งที่เป็นเจ้าของความสัมพันธ์
เมื่อใช้mappedByเป็นความรับผิดชอบของนักพัฒนาที่จะต้องรู้ว่าอะไรคือฝั่งที่เป็นเจ้าของและอัปเดตด้านที่ถูกต้องของความสัมพันธ์เพื่อที่จะทำให้เกิดการคงอยู่ของรีเลชันใหม่ในฐานข้อมูล