Hibernate 作為 ORM 框架,單條實體操作簡便,但面對百萬級數據時,一級緩存累積導致內存溢出(OOM)是常見痛點。本文系統講解三種批量處理方案:手動清理 Session 緩存、ScrollableResults 游標流式處理、HQL 批量執行語句。
核心思路:每累積 N 條數據,手動 flush() 刷入數據庫,clear() 清空 Session 緩存,並提交事務開啟新事務。
private void batchInsert() throws Exception {
Session session = HibernateUtil.currentSession();
Transaction tx = session.beginTransaction();
for (int i = 0; i < 100000; i++) {
User u = new User();
u.setName("user_" + i);
u.setAge(i);
u.setNationality("China");
session.save(u);
// 每 20 條刷新一次
if (i % 20 == 0) {
session.flush();
session.clear();
tx.commit();
tx = session.beginTransaction();
}
}
tx.commit();
HibernateUtil.closeSession();
}
關鍵配置:關閉二級緩存 hibernate.cache.use_second_level_cache=false,避免 SessionFactory 級緩存導致 OOM。
適用於需先查詢再更新的場景,使用只前進游標減少內存佔用:
private void batchUpdate() throws Exception {
Session session = HibernateUtil.currentSession();
Transaction tx = session.beginTransaction();
ScrollableResults users = session.createQuery("from User")
.setCacheMode(CacheMode.IGNORE) // 禁用緩存
.scroll(ScrollMode.FORWARD_ONLY);
int count = 0;
while (users.next()) {
User u = (User) users.get(0);
u.setName("新用戶_" + count);
if (++count % 20 == 0) {
session.flush();
session.clear();
}
}
tx.commit();
HibernateUtil.closeSession();
}
缺點:仍逐條發送 UPDATE 語句,性能一般。
Hibernate 支持類 SQL 的批量 DML,直接轉換為單條(或少量)SQL 執行,性能最優。
UPDATE | DELETE FROM? EntityName [WHERE condition]
FROM 關鍵字可選。String hqlUpdate = "update User set name = :newName";
int updatedEntities = session.createQuery(hqlUpdate)
.setString("newName", "新名字")
.executeUpdate(); // 返回受影響行數
String hqlDelete = "delete User";
int deletedEntities = session.createQuery(hqlDelete).executeUpdate();
joined-subclass),批量操作父類可能產生多條 SQL(分別更新父表、子表)。executeUpdate() 返回最後一條 SQL 影響的行數,非總影響行數。| 方案 | 適用場景 | 內存佔用 | SQL 執行次數 | 代碼複雜度 |
|---|---|---|---|---|
| 手動 flush/clear | 大量插入 | 低(可控) | N 條 INSERT | 中 |
| ScrollableResults | 需查詢後更新 | 低(流式) | N 條 UPDATE | 中 |
| HQL 批量 DML | 純屬性批量修改/刪除 | 極低 | 1~少量 SQL | 低 |
百萬級數據操作首選 HQL 批量 DML,單條 SQL 完成全表更新/刪除;需業務邏輯處理時使用 ScrollableResults 流式讀取配合手動清理緩存;純插入場景手動控制 flush/clear 間隔(建議 20~50 條)。務必關閉二級緩存並合理設置事務邊界,徹底解決 OOM 風險。