避免「查詢→載入物件→逐筆更新」的 N+1 問題與記憶體暴增:
// 刪除所有 User
String hql = "DELETE FROM User";
int count = session.createQuery(hql).executeUpdate();
// 批次更新
String hql = "UPDATE User SET status = :st WHERE lastLogin < :dt";
Query q = session.createQuery(hql)
.setParameter("st", "INACTIVE")
.setParameter("dt", cutoffDate);
int count = q.executeUpdate();
效能接近原生 JDBC,為大量資料處理首選。
極致效能場景直接用 JDBC 執行 SQL,省去 HQL 解析、物件初始化、快取處理。關鍵:手動同步快取 (evict/refresh) 確保一致性。
| 方法 | SQL 執行次數 | 快取利用 | 記憶體 | 適用場景 |
|---|---|---|---|---|
get() | 1 | 一級快取 → 資料庫 | 載入單一物件 | 需確認存在性、不依賴二級快取 |
load() | 0/1 | 一級 → 二級 → 資料庫 | Proxy 延遲載入 | 確定存在、善用二級快取 |
list() | 1 | 查詢快取 | 一次載入所有 | 結果集小、需全部資料 |
iterate() | 1 + N (視快取) | 二級快取 (逐筆) | 按需載入 | 結果集大、僅需部分、二級快存命中率高 |
@BatchSize 控制批次大小// 查詢時動態指定策略 (Criteria API)
User u = (User) session.createCriteria(User.class)
.setFetchMode("permissions", FetchMode.JOIN) // 此查詢用 Join
.add(Restrictions.idEq(uid))
.uniqueResult();
lazy="true",查詢時按需覆寫setCacheable(true) 且同步失效策略READ_COMMITTED 多為平衡點;長交易考慮樂觀鎖 (@Version)executeUpdate()get/load/list/iterate