5.1 一對一交流的多種形式
兩個 Entity 類之間的關係還有另一個有趣且相當具體的情況 - 一對一關係。
我稱這種情況非常具體,因為它更多地是關於 Java 對象而不是數據庫。在數據庫中,表與表之間的關係只有兩種選擇:
- 表行包含指向另一個表的 ID 的鏈接。
- 服務表用於多對多關係。
在實體類的情況下,可能有幾個註釋描述的選項:
- @嵌入式
- 單邊OneToOne
- 雙邊一對一
- @MapsId
下面我們將考慮其中最受歡迎的。
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
想像一下現在的情況:我們有一個源表 employee 和一個引用 employee 的任務。但是我們可以肯定地知道最多可以將一項任務分配給一個用戶。那麼我們就可以用註解來描述這種情況了@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;
}
Hibernate 將確保不僅一個任務有一個用戶,而且一個用戶只有一個任務。否則,這種情況實際上與@ManyToOne
.
5.4 雙邊OneToOne
前面的選項可能有點不方便,因為通常您不僅要將員工分配給任務,還要將任務分配給員工。
為此,您可以將 EmployeeTask 字段添加到 Employee 類並為其提供正確的註釋。
@Entity
@Table(name="employee")
class Employee {
@Column(name="id")
public Integer id;
@OneToOne(cascade = CascadeType.ALL, mappedBy="employee")
private EmployeeTask task;
}
重要的!employee 表沒有task_id字段,而是使用task表的employee_id字段來建立表與表之間的關係。
在對象之間建立連接看起來像這樣:
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();
GO TO FULL VERSION