Java 持久化/多對一
外觀
< Java 持久化
Java 中的 多對一 關係是指源物件有一個屬性引用另一個物件,即目標物件。例如典型的 Java 案例,一個物件持有對另一個物件的引用。多對一 關係可以是單向的。但是,目標物件通常具有指向源物件的逆關係。這將是目標物件中的 一對多 關係規範。Java 和 JPA 中的所有關係都是單向的,也就是說,如果源物件引用目標物件,則不能保證目標物件也與源物件有關係。這與關係資料庫不同,在關係資料庫中,關係透過外部索引鍵和查詢來定義,以便始終存在反向查詢。
在 JPA 中,多對一 關係透過 @ManyToOne 註解或 <many-to-one> 元素指定。@ManyToOne 註解通常伴隨 @JoinColumn 註解。@JoinColumn 註解指定了關係如何對映到資料庫(在資料庫中表示)。@JoinColumn 定義了源物件中用於查詢(連線)目標物件的外部鍵列名稱(@JoinColumn(name = "..."))。
如果在目標物件中指定了反向 一對多 關係,那麼目標物件中的 @OneToMany 註解必須包含 mappedBy 屬性來定義這個反向關係。
JPA 還定義了 一對一 關係,它類似於 多對一 關係,除了反向關係(如果定義了的話)是一個 一對一 關係。JPA 中 一對一 和 多對一 關係的主要區別在於,多對一 始終包含從源物件表的外部鍵到目標物件表的外部鍵,而 一對一 關係的外部鍵可能位於源物件表或目標物件表中。
員工(表)
| 員工 ID | 姓名 | 姓氏 | 薪資 | 經理 ID |
| 1 | 鮑勃 | 韋 | 50000 | 2 |
| 2 | 莎拉 | 史密斯 | 75000 | 空 |
電話(表)
| ID | 型別 | 區號 | 電話號碼 | 所有者 ID |
| 1 | 家庭 | 613 | 792-0000 | 1 |
| 2 | 工作 | 613 | 896-1234 | 1 |
| 3 | 工作 | 416 | 123-4444 | 2 |
@Entity
public class Phone {
@Id
private long id;
...
// Specifies the PHONE table does not contain an owner column, but
// an OWNER_ID column with a foreign key. And creates a join to
// lazily fetch the owner
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="OWNER_ID")
private Employee owner;
...
}
// Specification of the reverse OneToMany relationship in Employee
@Entity
public class Employee {
@Id
private long emp_id;
...
// The 'mappedBy = "owner"' attribute specifies that
// the 'private Employee owner;' field in Phone owns the
// relationship (i.e. contains the foreign key for the query to
// find all phones for an employee.)
@OneToMany(mappedBy = "owner")
private List<Phone> phones;
...
<entity name="Phone" class="org.acme.Phone" access="FIELD">
<attributes>
<id name="id"/>
<many-to-one name="owner" fetch="LAZY">
<join-column name="OWNER_ID"/>
</many-to-one>
</attributes>
</entity>
- 參見 透過一對一關係生成主鍵.
- 如果你在兩個不同的對映中使用相同的欄位,通常需要使用
insertable, updatable = false使其中一個欄位變為只讀。 - 參見 目標外部索引鍵、主鍵連線列、級聯主鍵.
- 這通常是因為你在
一對一關係中錯誤地映射了外部索引鍵。
- 如果你的 JPA 提供程式不支援引用完整性,或者無法解析雙向約束,也會發生這種情況。在這種情況下,你可能需要移除約束,或者使用
EntityManagerflush()來確保物件寫入的順序。
- 確保你設定了物件的
一對一值,如果一對一是雙向一對多關係的一部分,確保你在將物件新增到一對多中時設定了物件的一對一,JPA 不會為你維護雙向關係。 - 還要檢查你是否正確定義了
JoinColumn,確保你沒有設定insertable, updateable = false或使用PrimaryKeyJoinColumn。
在複雜的資料模型中,如果外部索引鍵/JoinColumn 與其他 多對一 或 Basic 對映共享,則可能需要使用目標外部索引鍵或只讀 JoinColumn 來對映 多對一。
