物件導向領域模型中,實體間除繼承外,核心關係為關聯:一對一、一對多、多對一、多對多。OpenJPA 以標準 JPA 註解 (@OneToOne、@OneToMany、@ManyToOne、@ManyToMany) 實現透明關聯映射,並支援級聯操作與載入策略控制。
場景:Book (書籍) 與 BookExtend (前言) 為一對一。資料庫採唯一外鍵模式:Book 表含 extendID 參照 BookExtend.ID。
@OneToOne)targetEntity:關聯實體類型(通常可推斷省略)。mappedBy:雙向關聯時,指定對方擁有關係的屬性名(僅在非擁有方使用)。cascade:級聯操作類型 (PERSIST, REMOVE, MERGE, REFRESH, ALL)。fetch:EAGER (預設,立即載入) 或 LAZY (延遲載入)。optional:關聯對象是否可為 null (預設 true)。@JoinColumn 精確控制外鍵欄位name:擁有方表中外鍵欄位名 (如 extendID)。referencedColumnName:被參照表欄位名 (預設主鍵,可指定其他唯一鍵)。未指定時,預設外鍵欄位為 屬性名_ID (如 bookExtend_ID)。
// Book.java (擁有方)
@Entity(name="Book")
public class Book {
@Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="ID")
private int id;
@Basic @Column(name="NAME")
private String name;
@OneToOne(optional=true, cascade=CascadeType.ALL)
@JoinColumn(name="extendID") // Book 表外鍵欄位
public BookExtend bookExtend;
// getter/setter...
}
// BookExtend.java (被參照方,無映射註解)
@Entity
public class BookExtend {
@Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="ID")
private int id;
@Basic @Column(name="NAME")
private String name; // 前言內容
// getter/setter...
}
僅持久化 Book,BookExtend 自動持久化並建立關聯:
Book book = new Book(); book.setName("Web Services實踐");
BookExtend ext = new BookExtend(); ext.setName("前言 本書重點...");
book.setBookExtend(ext);
em.persist(book); // 單一操作完成雙表插入與關聯更新
生成 SQL:INSERT Book → INSERT BookExtend → UPDATE Book SET extendID=?。
em.merge(book) 同步更新雙方狀態。
JPQL 批量刪除 DELETE FROM Book WHERE id=:id 觸發級聯刪除 BookExtend,無需先載入物件。
| 關聯類型 | 註解 | 典型場景 | 擁有方/映射關鍵 |
|---|---|---|---|
| 一對多 | @OneToMany | 部門-員工、訂單-明細 | 「多」方為擁有方,用 @ManyToOne + @JoinColumn;「一」方用 mappedBy 指向「多」方屬性 |
| 多對一 | @ManyToOne | 員工-部門、明細-訂單 | 本方為擁有方,必須 @JoinColumn 指定外鍵 |
| 多對多 | @ManyToMany | 學生-課程、用戶-角色 | 雙方均用 @ManyToMany,一擁有方用 @JoinTable 定義中間表,另一方用 mappedBy |
@OneToMany/@ManyToMany 支援 @JoinColumns (含多個 @JoinColumn) 處理複合外鍵。
mappedBy,避免重複外鍵與更新衝突。CascadeType.REMOVE 可能引發大範圍連鎖刪除,生產環境建議顯式控制或軟刪除。@OneToMany, @ManyToMany) 預設 LAZY,單值關聯 (@OneToOne, @ManyToOne) 預設 EAGER。根據業務訪問模式調整,避免 N+1 問題。addChild/removeChild 方法統一管理。OpenJPA 以少量標準註解實現豐富的關聯映射:@OneToOne/@ManyToOne 處理單值關聯,@OneToMany/@ManyToMany 處理集合關聯,配合 @JoinColumn/@JoinTable 精確控制資料庫外鍵與中間表。掌握擁有方概念、級聯語義、載入策略,是設計高效、正確 ORM 模型的關鍵。