在上一篇《Hibernate 總結(一)》中,我們簡要回顧了一級快取、快照機制以及基本的增刪改查操作。本文將重點探討兩張表之間的級聯操作,這是 Hibernate 實際開發中極其重要且常見的場景。
Hibernate 中的級聯主要涉及三種關聯關係:many-to-many(多對多)、one-to-many(一對多)與 many-to-one(多對一)。理解這三種關係的配置差異,是掌握級聯操作的關鍵。
我們以「客戶」與「訂單」為例,一個客戶可以擁有多個訂單,而一個訂單僅屬於一個客戶。
// Customer.java
public class Customer {
private Integer id;
private String name;
private Set<Order> orders = new HashSet<>(); // 1 對多
// getter/setter 省略
}
// Order.java
public class Order {
private Integer id;
private String name;
private Customer customer; // 多對 1
// getter/setter 省略
}
級聯的核心在於映射文件中的 inverse 與 cascade 兩個屬性的配合:
delete(級聯刪除)、all(全部操作)、none(預設無級聯)。<!-- Customer.hbm.xml -->
<set name="orders" inverse="true" cascade="save-update">
<key column="cid"/> <!-- Order 表中的外鍵欄位 -->
<one-to-many class="Order"/>
</set>
<!-- Order.hbm.xml -->
<many-to-one name="customer" column="cid" class="Customer"/>
在保存時,只需設置關聯關係並保存客戶對象(或根據 cascade 策略保存訂單),Hibernate 會自動發送高效的 SQL:
Customer c = new Customer(); c.setName("King");
Order o1 = new Order(); o1.setName("炒面");
Order o2 = new Order(); o2.setName("肉");
// 關鍵:由擁有外鍵的一方維護關係
o1.setCustomer(c);
o2.setCustomer(c);
session.save(c); // 因 cascade="save-update",o1、o2 會被自動保存
// 僅執行 3 條 INSERT SQL
session.delete(customer) 即可級聯刪除所有訂單,極其方便。配置 cascade="save-update" 時,修改持久態對象的關聯集合內容(如修改訂單名稱),事務提交時會自動同步到資料庫,無需顯式調用 update()。
多對多關係需要一張中間表(如 t_selectcourse)來維護關聯。雙方都使用 <set> 並指定 table 屬性。
雙方都配置集合時,必須有一方設置 inverse="true",放棄關係維護權,否則會產生重複的中間表記錄。
<!-- Student.hbm.xml 維護關係 -->
<set name="courses" cascade="save-update" table="t_selectcourse">
<key column="sid"/>
<many-to-many class="Course" column="cid"/>
</set>
<!-- Course.hbm.xml 放棄維護 -->
<set name="students" inverse="true" table="t_selectcourse">
<key column="cid"/>
<many-to-many class="Student" column="sid"/>
</set>
Student s1 = new Student(); s1.setName("King");
Course c1 = new Course(); c1.setName("數學");
Course c2 = new Course(); c2.setName("英語");
// 由學生一方維護關係
s1.getCourses().add(c1);
s1.getCourses().add(c2);
session.save(s1); // 級聯保存課程及中間表關係
提示:多對多的級聯刪除與更新邏輯較為複雜,需謹慎設計中間表數據完整性,實際項目中常建議拆解為兩個一對多關係處理。
inverse="true" 在一對多端)。cascade="all" 或 delete,防止誤刪除關鍵數據。查詢操作涉及加載策略(立即/延遲加載)、N+1 問題等進階主題,將在下一篇詳細闡述。掌握好級聯操作,是駕馭 Hibernate 複雜對象圖持久化的基石。