3.1 การแมปเอนทิตีที่ขึ้นต่อกัน
ใน SQL คุณสามารถเขียนแบบสอบถามโดยใช้ JOIN เป็นไปได้ไหมที่จะทำเช่นเดียวกันใน HQL? คำตอบสั้น ๆ คือใช่ แต่คำตอบแบบเต็มจะน่าสนใจยิ่งขึ้น
อันดับแรก เมื่อเราเขียน JOIN ใน SQL มักจะหมายความว่าตารางหนึ่งอ้างอิงถึงอีกตารางหนึ่ง ตัวอย่างเช่น ตารางงานมีคอลัมน์ customer_id ที่อ้างถึงคอลัมน์ id ของตารางพนักงาน
การพึ่งพานี้สามารถอธิบายได้โดยใช้คำอธิบายประกอบใน Hibernate ขั้นแรก ให้สร้างเอนทิตีสำหรับตารางของเรา ก่อนอื่นมาอธิบายตารางพนักงาน:
@Entity
@Table(name="employee")
class Employee {
@Column(name="id")
public Integer id;
@Column(name="name")
public String name;
@Column(name="salary")
public Integer salary;
@Column(name="join_date")
public Date joinDate;
}
และ คลาส EmployeeTaskสำหรับ ตาราง งาน :
@Entity
@Table(name="task")
class EmployeeTask {
@Column(name="id")
public Integer id;
@Column(name="name")
public String name;
@Column(name="employee_id")
public Integer employeeId;
@Column(name="deadline")
public Date deadline;
}
ทุกอย่างดี แต่มีข้อเสนอแนะอย่างหนึ่ง ลองดูที่ ช่อง รหัสพนักงานในตัวอย่างสุดท้าย:
@Column(name="employee_id")
public Integer employeeId;
คุณสังเกตเห็นอะไรแปลก ๆ หรือไม่? ถ้าไม่ ก็แสดงว่าคุณได้สร้างวิธีคิดในภาษา SQL แล้ว
สิ่งหนึ่งคือในภาษา Java เรามักจะอธิบายการพึ่งพาดังกล่าวแตกต่างกันเล็กน้อย:
public Employee employee;
เราไม่จำเป็นต้องระบุid เรามักจะระบุตัวแปรที่เก็บการอ้างอิงถึง วัตถุ Employee หรือเก็บค่าว่างหากไม่มีวัตถุดังกล่าว
และไฮเบอร์เนตช่วยให้เราสามารถอธิบายสถานการณ์ดังกล่าวโดยใช้คำอธิบายประกอบ:
@ManyToOne
@JoinColumn(name="employee_id", nullable=true)
public Employee employee;
คำอธิบายประกอบ@ManyToOne
จะบอก Hibernate ว่า เอนทิ ตี EmployeeTask จำนวนมาก สามารถอ้างถึง เอน ทิ ตี Employee เดียว
และคำอธิบายประกอบจะ@JoinColumn
ระบุชื่อของคอลัมน์ที่ จะใช้ id ข้อมูลที่จำเป็นอื่น ๆ ทั้งหมดจะนำมาจากคำอธิบายประกอบของคลาสพนักงาน
ผลลัพธ์สุดท้ายจะมีลักษณะดังนี้:
@Entity
@Table(name="task")
class EmployeeTask
{
@Column(name="id")
public Integer id;
@Column(name="name")
public String name;
@ManyToOne
@JoinColumn(name="employee_id", nullable=true)
public Employee employee;
@Column(name="deadline")
public Date deadline;
}
3.2 การใช้การรวมใน HQL
และตอนนี้ มาดูวิธีการเขียนแบบสอบถามไปยังเอนทิตีที่เกี่ยวข้องใน HQL
สถานการณ์แรก
เรามีพนักงาน (Employee) และเราต้องการรับรายการงานของเขา ต่อไปนี้คือลักษณะของแบบสอบถามใน SQL:
SELECT task.* FROM task JOIN employee ON task.employee_id = employee.id
WHERE employee.name = "Ivan Ivanovich";
และตอนนี้มาเขียนแบบสอบถามเดียวกันใน HQL:
from EmployeeTask where employee.name = "Ivan Ivanovich"
คลาสEmployeeTaskมี ฟิลด์ พนักงานและมี ฟิลด์ ชื่อดังนั้นแบบสอบถามนี้จะใช้งานได้
สถานการณ์ที่สอง
ส่งคืนรายชื่อพนักงานที่มีงานค้างชำระ ต่อไปนี้คือลักษณะของแบบสอบถามใน SQL:
SELECT DISTINCT employee.*
FROM task JOIN employee ON task.employee_id = employee.id
WHERE task.deadline < CURDATE();
DISTINCT
ใช้เนื่องจากสามารถมีงานหลายอย่างที่กำหนดให้กับผู้ใช้คนเดียว
และตอนนี้มาเขียนแบบสอบถามเดียวกันใน HQL:
select distinct employee from EmployeeTask where deadline < CURDATE();
พนักงานในแบบสอบถามนี้เป็นเขตข้อมูลของ คลาส EmployeeTask
สถานการณ์ที่สาม
มอบหมายงานที่ยังไม่ได้รับมอบหมายทั้งหมดให้กับผู้อำนวยการ แบบสอบถาม SQL จะมีลักษณะดังนี้:
UPDATE task SET employee_id = 4 WHERE employee_id IS NULL
และตอนนี้มาเขียนแบบสอบถามเดียวกันใน HQL:
update EmployeeTask set employee = :user where employee is null
คำถามสุดท้ายคือคำถามที่ยากที่สุด เราจำเป็นต้องส่ง ID ผู้อำนวยการ แต่คลาส EmployeeTask ไม่มีฟิลด์ที่คุณสามารถเขียน id ได้ แต่จะประกอบด้วยฟิลด์ Employee ซึ่งคุณต้องกำหนดการอ้างอิงให้กับวัตถุประเภท Employee
ใน Hibernate ปัญหานี้แก้ไขได้ด้วยความช่วยเหลือของพารามิเตอร์การค้นหาที่ส่งผ่านไปยังวัตถุ Query และใน HQL เอง พารามิเตอร์ดังกล่าวเขียนผ่านโคลอน:user
: แต่เราจะพูดถึงเรื่องนี้ในภายหลัง
GO TO FULL VERSION