6.1 การจัดการการพึ่งพาอย่างลึกซึ้ง
และสิ่งที่เป็นประโยชน์และน่าสนใจเพิ่มเติมเกี่ยวกับ คำอธิบายประกอบ @OneToManyและอื่นๆ พวกเขาทั้งหมดมี 4 ตัวเลือกที่ใช้กันทั่วไป:
- น้ำตก = CascadeType.ALL
- orphanRemoval = จริง
- ดึงข้อมูล = FetchType.LAZY
ตอนนี้เราจะวิเคราะห์รายละเอียดเพิ่มเติม และเราจะเริ่มต้นด้วยสิ่งที่น่าสนใจที่สุด - CascadeType . พารามิเตอร์นี้กำหนดว่าจะเกิดอะไรขึ้นกับเอนทิตีที่ขึ้นต่อกันหากเราเปลี่ยนเอนทิตีหลัก
ข้อกำหนด JPA มีค่าต่อไปนี้สำหรับพารามิเตอร์นี้:
- ทั้งหมด
- ยังคงมีอยู่
- ผสาน
- ลบ
- รีเฟรช
- ถอด
อย่างไรก็ตาม Hibernate ได้ขยายข้อกำหนดนี้ออกเป็นสามตัวเลือกเพิ่มเติม:
- ทำซ้ำ
- บันทึก_อัปเดต
- ล็อค
แน่นอนว่ามีความคล้ายคลึงกันอย่างมากกับฐานข้อมูลและ CONSTRANIS อย่างไรก็ตามยังมีความแตกต่าง ไฮเบอร์เนตพยายามซ่อนการทำงานจริงกับฐานข้อมูลให้ได้มากที่สุด ดังนั้น Hibernate Cascades เหล่านี้จึงเกี่ยวกับวัตถุเอนทิตีทุกประการ
6.2 ประเภทคาสเคด
พารามิเตอร์ cascade อธิบายถึงสิ่งที่จะเกิดขึ้นกับออบเจกต์ที่ขึ้นต่อกันหากเราเปลี่ยนพาเรนต์ (ออบเจ็กต์หลัก) บ่อยที่สุด พารามิเตอร์นี้ใช้ร่วมกับคำอธิบายประกอบที่อธิบายการขึ้นต่อกันของวัตถุ:
ตัวอย่าง:
OneToOne(cascade = CascadeType.ALL)
หรือแบบนี้:
@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
นอกจากนี้ยังสามารถเขียนเป็นคำอธิบายประกอบแยกต่างหาก:
@Cascade({ org.hibernate.annotations.CascadeType.ALL })
ตอนนี้เรามาพูดเพิ่มเติมเกี่ยวกับความหมายของคำอธิบายประกอบเหล่านี้
6.3 ทั้งหมด คงอยู่ รวม
CascadeType.ALL
หมายความว่าการดำเนินการทั้งหมดที่เราดำเนินการกับวัตถุหลักจะต้องทำซ้ำสำหรับวัตถุที่ขึ้นต่อกัน
CascadeType.PERSIST
หมายความว่าหากเราบันทึกวัตถุหลักลงในฐานข้อมูล ก็จะต้องทำเช่นเดียวกันกับวัตถุที่ขึ้นต่อกัน ตัวอย่าง:
@Entity
@Table(name="employee")
class Employee {
@Column(name="id")
public Integer id;
@OneToOne(cascade = CascadeType.PERSIST, mappedBy="task")
private EmployeeTask task;
}
ตัวอย่างการทำงานกับคลาสนี้:
Employee director = new Employee();
EmployeeTask task = new EmployeeTask();
director.task = task;
session.persist(director);
session.flush();
เราบันทึกเฉพาะวัตถุประเภท Employee ซึ่งขึ้นอยู่กับวัตถุ EmployeeTask จะถูกบันทึกลงในฐานข้อมูลโดยอัตโนมัติ
CascadeType.MERGE
หมายความว่าหากเราอัปเดตวัตถุหลักในฐานข้อมูล ก็จะต้องทำเช่นเดียวกันกับวัตถุที่ขึ้นต่อกัน
6.4 ลบ ลบ ปลดออก
CascadeType.REMOVE
หมายความว่าหากเราลบวัตถุหลักในฐานข้อมูล ก็จะต้องทำเช่นเดียวกันกับวัตถุที่ขึ้นต่อกัน
CascadeType.DELETE
หมายความว่าเหมือนกัน เหล่านี้เป็นคำพ้องความหมาย จากข้อกำหนดที่แตกต่างกัน
CascadeType.DETACH
หมายความว่าหากเราลบวัตถุหลักออกจากเซสชัน ก็จะต้องทำเช่นเดียวกันกับวัตถุที่ขึ้นต่อกัน ตัวอย่าง:
@Entity
@Table(name="employee")
class Employee {
@Column(name="id")
public Integer id;
@OneToOne(cascade = CascadeType.DETACH, mappedBy="task")
private EmployeeTask task;
}
ตัวอย่างการทำงานกับคลาสนี้:
Employee director = new Employee();
EmployeeTask task = new EmployeeTask();
director.task = task;
director.task = task;
session.flush();
assertThat(session.contains(director)).isTrue();
assertThat(session.contains(task)).isTrue();
session.detach(director);
assertThat(session.contains(director)).isFalse();
assertThat(session.contains(task)).isFalse();
CascadeType.REFRESH
และ CascadeType.SAVE_UPDATE
ทำงานในลักษณะเดียวกับที่เราคาดหวัง - พวกมันทำซ้ำการกระทำที่ทำกับวัตถุหลักไปยังวัตถุที่ขึ้นต่อกัน
6.5 ตัวเลือกการกำจัดเด็กกำพร้า
นอกจากนี้ บางครั้งคุณอาจเจอorphan
พารามิเตอร์ นี่เป็นคำย่อสำหรับการกำจัดเด็กกำพร้า ใช้เพื่อให้แน่ใจว่าไม่มีเอนทิตีย่อยที่ไม่มีเอนทิตีหลัก
OneToOne(orphan = true)
หากตั้งค่าพารามิเตอร์นี้เป็นจริง เอนทิตีย่อยจะถูกลบหากหายไปลิงค์ทั้งหมด. Cascade.REMOVE
มัน ไม่เหมือนกับ
คุณอาจมีสถานการณ์ที่เอนทิตีหลักหลายรายการอ้างถึงลูกคนเดียว จากนั้นจะเป็นประโยชน์ที่จะไม่ถูกลบพร้อมกับการลบเอนทิตีหลัก แต่ถ้าการอ้างอิงถึงเอนทิตีทั้งหมดจะเป็นโมฆะเท่านั้น
สมมติว่าคุณมีชั้นเรียน:
@Entity
@Table(name="user")
class Employee {
@Column(name="id")
public Integer id;
@OneToMany(cascade = CascadeType.ALL, orphan = true)
@JoinColumn(name = "employee_id")
private Set<EmployeeTask> tasks = new HashSet<EmployeeTask>();
}
Employee director = session.find(Employee.class, 4);
EmployeeTask task = director.tasks.get(0);
director.tasks.remove(task)
session.persist(director);
session.flush();
วัตถุ EmployeeTask จะถูกลบเนื่องจากไม่มีการอ้างอิงเหลืออยู่ ในเวลาเดียวกัน ไม่มีใครลบวัตถุหลัก
6.6 ตัวเลือกการดึงข้อมูล
ตัวเลือกการดึงข้อมูลช่วยให้คุณควบคุมวิธีการโหลดวัตถุที่ขึ้นต่อกันได้ โดยปกติจะใช้หนึ่งในสองค่า:
FetchType.LAZY
FetchType.EAGER
นี่เป็นหัวข้อที่น่าสนใจมากซึ่งมีข้อผิดพลาดมากมาย ดังนั้นฉันควรพูดถึงเรื่องนี้ในการบรรยายแยกต่างหาก