2.1 表級鏈接
我們已經看到 Hibernate 如何在輔助表中存儲集合。現在讓我們弄清楚如何組織存儲真實實體類的完整表之間的關係。
Hibernate中實體類之間的關係有四種:
- 一對一_ _
- 一對多_ _
- 多對一_ _
- 多對多_ _
我們將從最簡單的選項開始分析——多對一。
您已經遇到過 SQL 中表之間的這種關係。它通常是這樣的:
ID | 姓名 | 職業 | 薪水 | 年齡 | 加入日期 |
---|---|---|---|---|---|
1個 | 伊万諾夫伊万 | 程序員 | 100000 | 25 | 2012-06-30 |
2個 | 彼得羅夫彼得 | 程序員 | 80000 | 23 | 2013-08-12 |
3個 | 伊万諾夫謝爾蓋 | 測試儀 | 40000 | 三十 | 2014-01-01 |
4個 | 拉比諾維奇·莫伊沙 | 導演 | 200000 | 35 | 2015-05-12 |
5個 | 基連科阿納斯塔西婭 | 辦公室主管 | 40000 | 25 | 2015-10-10 |
6個 | 瓦斯卡 | 貓 | 1000 | 3個 | 2018-11-11 |
員工表:
該表包含以下列:
- 標識符整數
- 名稱VARCHAR
- 職業VARCHAR
- 薪水整數
- 年齡整數
- join_date日期
這就是包含員工任務的任務表的樣子:
ID | 員工ID | 姓名 | 最後期限 |
---|---|---|---|
1個 | 1個 | 修復一個前端bug | 2022-06-01 |
2個 | 2個 | 修復後端的一個bug | 2022-06-15 |
3個 | 5個 | 買咖啡 | 2022-07-01 |
4個 | 5個 | 買咖啡 | 2022-08-01 |
5個 | 5個 | 買咖啡 | 2022-09-01 |
6個 | (無效的) | 打掃辦公室 | (無效的) |
7 | 4個 | 享受生活 | (無效的) |
8個 | 6個 | 享受生活 | (無效的) |
該表只有 4 列:
- id – 唯一的任務編號(和表中的行);
- employee_id – 分配任務的員工表中的員工 ID;
- 名稱——任務的名稱和描述;
- deadline - 任務必須完成的時間。
我們看到任務表中的許多行可以引用員工表中的單個條目。這種表級關係稱為多對一。
2.2 與Java類級別的關係
除了表級別的通信,您還可以在 Hibernate 中的實體類級別組織通信。這是通過註釋完成的@ManyToOne
。
但首先,讓我們創建兩個類:Employee和EmployeeTask:
@Entity
@Table(name="employee")
class Employee {
@Column(name="id")
public Integer id;
@Column(name="name")
public String name;
@Column(name="occupation")
public String occupation;
@Column(name="salary")
public Integer salary;
@Column(name="join_date")
public Date join;
}
第二類存儲員工工作:
@Entity
@Table(name="task")
class EmployeeTask {
@Column(name="id")
public Integer id;
@Column(name="name")
public String description;
@Column(name="employee_id")
public Integer employeeId;
@Column(name="deadline")
public Date deadline;
}
這些類都很好,但是它們之間沒有關係可以反映 EmployeeTask 類的 employeeId 字段引用 Employee 類的 id 字段這一事實。是時候修復它了
2.3 @ManyToOne註解。
首先,在 Java 中我們習慣於操作對象(和對象引用)而不是它們的 id。所以首先,讓我們指向一個 Employee 類型的對象,而不是 EmployeeTask 類中的 employeeId 字段。這是我們的新課程的樣子:
@Entity
@Table(name="task")
class EmployeeTask {
@Column(name="id")
public Integer id;
@Column(name="name")
public String description;
@ManyToOne
@JoinColumn(name = "employee_id")
public Employee employee;
@Column(name="deadline")
public Date deadline;
}
在註釋 的幫助下@ManyToOne
,我們已經指出許多 EmployeeTask 對象可以引用一個 Employee 類型的對象。此外,使用註釋 @JoinColumn
,我們指出了 Employee 對象的 ID 存儲在表的哪一列中。
2.4 請求示例
現在讓我們展示一些 Hibernate 如何與這些相關類一起工作的例子。
場景一
讓我們編寫一個查詢來找出已分配給特定用戶的所有任務。下面是這個查詢在 HQL 中的樣子:
from EmployeeTask where employee.name = "Ivan Ivanovich"
您可以簡單地通過一個點來引用依賴類的字段。很舒服。但是讓我們仍然以 Java 代碼的形式編寫這個查詢:
String hql = "from EmployeeTask where employee.name = :username";
Query<EmployeeTask> query = session.createQuery( hql, EmployeeTask.class);
query.setParameter("username", "Ivan Ivanovich");
List<EmployeeTask> resultLIst = query.list();
情景二
讓我們編寫一個查詢,返回一個有逾期任務的員工列表。如果截止日期已過,則任務已過期。下面是該查詢在 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();
此查詢中的 Employee 是 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 類型對象的引用。
Employee director = session.get(Employee.class, 4);
String hql = "update EmployeeTask set employee = :user where employee is null";
Query<EmployeeTask> query = session.createQuery(hql, EmployeeTask.class);
query.setParameter("user", director);
query.executeUpdate();
GO TO FULL VERSION