5.1 รูปแบบต่างๆ ของการสื่อสารตัวต่อตัว
มีอีกกรณีหนึ่งที่น่าสนใจและค่อนข้างเฉพาะเจาะจงของความสัมพันธ์ระหว่างสองคลาสของเอนทิตี นั่นคือความสัมพันธ์แบบหนึ่งต่อหนึ่ง
ฉันเรียกกรณีนี้ว่าเฉพาะเจาะจงมาก เนื่องจากเป็นเรื่องเกี่ยวกับวัตถุ Java มากกว่าฐานข้อมูล ในฐานข้อมูล มีเพียงสองตัวเลือกสำหรับความสัมพันธ์ระหว่างตาราง:
- แถวของตารางมีลิงก์ไปยังรหัสของตารางอื่น
- ตารางบริการใช้สำหรับความสัมพันธ์แบบกลุ่มต่อกลุ่ม
ในกรณีของคลาสเอนทิตี อาจมีตัวเลือกที่อธิบายโดยคำอธิบายประกอบหลายรายการ:
- @ฝัง
- OneToOne ด้านเดียว
- ทวิภาคีวันทูวัน
- @แผนที่รหัส
ด้านล่างเราจะพิจารณาความนิยมสูงสุดของพวกเขา
5.2 แบบฝังตัว
อย่างไรก็ตาม เราได้พิจารณา ตัวเลือกการสื่อสาร แบบตัวต่อตัวที่ง่ายที่สุด แล้ว นั่นคือคำอธิบาย @Embedded
ประกอบ ในกรณีนี้ เรามีสองคลาสที่จัดเก็บไว้ในตารางเดียวกันในฐานข้อมูล
สมมติว่าเราต้องการจัดเก็บที่อยู่ของผู้ใช้ใน คลาส UserAddress :
@Embeddable
class UserAddress {
@Column(name="user_address_country")
public String country;
@Column(name="user_address_city")
public String city;
@Column(name="user_address_street")
public String street;
@Column(name="user_address_home")
public String home;
}
จากนั้นเราต้องเพิ่มฟิลด์ที่มีที่อยู่นี้ใน คลาส User :
@Entity
@Table(name="user")
class User {
@Column(name="id")
public Integer id;
@Embedded
public UserAddress address;
@Column(name="created_date")
public Date createdDate;
}
Hibernate จะทำส่วนที่เหลือ: ข้อมูลจะถูกจัดเก็บไว้ในตารางเดียว แต่เมื่อเขียนแบบสอบถาม HQL คุณจะต้องดำเนินการกับฟิลด์คลาส
ตัวอย่างแบบสอบถาม HQL:
select from User where address.city = 'Paris'
5.3 วันทูวันด้านเดียว
ลองนึกภาพสถานการณ์ตอนนี้: เรามีพนักงานตารางต้นทางและงานที่อ้างถึงพนักงาน แต่เรารู้แน่นอนว่าสามารถมอบหมายงานให้กับผู้ใช้หนึ่งคนได้สูงสุดหนึ่งงาน จากนั้นเราสามารถใช้คำอธิบายประกอบเพื่ออธิบายสถานการณ์นี้@OneToOne
ได้
ตัวอย่าง:
@Entity
@Table(name="task")
class EmployeeTask {
@Column(name="id")
public Integer id;
@Column(name="name")
public String description;
@OneToOne
@JoinColumn(name = "employee_id")
public Employee employee;
@Column(name="deadline")
public Date deadline;
}
ไฮเบอร์เนตจะตรวจสอบให้แน่ใจว่าไม่ได้มีเพียงงานเดียวที่มีผู้ใช้เพียงคนเดียว แต่ยังรวมถึงผู้ใช้หนึ่งรายที่มีงานเดียวเท่านั้น มิฉะนั้น กรณีนี้ก็ไม่ต่างจาก@ManyToOne
.
5.4 ทวิภาคีวันทูวัน
ตัวเลือกก่อนหน้านี้อาจไม่สะดวกเล็กน้อย เพราะบ่อยครั้งที่คุณต้องการมอบหมายงานให้พนักงาน ไม่เพียงแต่งานเท่านั้น แต่ยังมอบหมายงานให้พนักงานด้วย
ในการทำเช่นนี้ คุณสามารถเพิ่มฟิลด์ EmployeeTask ให้กับคลาสพนักงานและใส่คำอธิบายประกอบที่ถูกต้อง
@Entity
@Table(name="employee")
class Employee {
@Column(name="id")
public Integer id;
@OneToOne(cascade = CascadeType.ALL, mappedBy="employee")
private EmployeeTask task;
}
สำคัญ!ตารางพนักงานไม่มี เขต ข้อมูลรหัสงานแต่ จะใช้เขต ข้อมูลรหัสพนักงาน ของ ตารางงาน แทนเพื่อสร้างความสัมพันธ์ระหว่าง ตาราง
การสร้างการเชื่อมต่อระหว่างวัตถุมีลักษณะดังนี้:
Employee director = session.find(Employee.class, 4);
EmployeeTask task = session.find(EmployeeTask.class, 101);
task.employee = director;
director.task = task;
session.update(task);
session.flush();
หากต้องการลบลิงก์ จะต้องลบลิงก์ออกจากออบเจ็กต์ทั้งสองด้วย:
Employee director = session.find(Employee.class, 4);
EmployeeTask task = director.task;
task.employee = null;
session.update(task);
director.task = null;
session.update(director);
session.flush();