首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Hibernate 3 學習筆記(五):深入解析 saveOrUpdate 方法

     編輯:Java 相關知識

前言

在前幾篇筆記中,我們已經熟悉了 Hibernate 的基本配置與 CRUD 操作。本篇將重點探討 saveOrUpdate() 這個極具實用價值的方法,它能根據對象的狀態自動決定執行「新增」還是「更新」操作,極大地簡化了業務邏輯代碼。

映射文件配置關鍵點

要讓 saveOrUpdate() 正確運作,映射文件(User.hbm.xml)中的 <id> 元素配置至關重要,特別是 unsaved-value 屬性:

<id name="id" column="id" type="java.lang.Integer" unsaved-value="null">
    <generator class="native" />
</id>

unsaved-value="null" 表示:當 ID 為 null 時視為「瞬時對象」(執行 save),否則視為「脫管對象」(執行 update)。這是預設行為,也是最常用的策略。

核心代碼示例

以下測試代碼展示了兩種典型場景:

// 場景一:指定 ID 為 2,對象已存在於數據庫 → 執行 UPDATE
User user = new User();
user.setId(2);                      // 關鍵:設置非 null ID
user.setName("chenyan");
user.setAge(24);
session.saveOrUpdate(user);         // 執行 update user set name=?, age=? where id=?

// 場景二:不設置 ID,ID 為 null → 執行 INSERT
user = new User();
user.setName("yangye");
user.setAge(23);
session.saveOrUpdate(user);         // 執行 insert into user (name, age) values (?, ?)

運行結果分析

控制台輸出清晰地印證了上述邏輯:

Hibernate: update user set name=?, age=? where id=?
========================================
Hibernate: insert into user (name, age) values (?, ?)
========================================
id      name/age
1       shenbin/28
2       chenyan/24
3       yangye/23

第一次調用發出 UPDATE 語句,修改了 ID 為 2 的記錄;第二次調用發出 INSERT 語句,新增了一條 ID 為 3 的記錄。

unsaved-value 可選值詳解

值行為
nullID 為 null 時執行 save(預設)
any總是執行 save
none總是執行 update
validID 為 null 或指定值時執行 save

常見陷阱:NonUniqueObjectException

在同一個 Session 中,若先查詢出對象,再嘗試用 saveOrUpdate() 處理一個相同 ID 的新對象實例,會拋出異常:

org.hibernate.NonUniqueObjectException: 
a different object with the same identifier value was already associated with the session: [com.hb3.pack_01.model.User#2]

原因:Session 緩存中已存在該 ID 的對象,Hibernate 禁止兩個不同實例對應同一個資料庫標識符。

解決方案:

  • 開啟新的 Session 處理更新操作
  • 使用 session.merge() 替代(會將脫管對象狀態合併到持久化對象中)
  • 在查詢後立即 evict() 對象,使其脫管

總結

saveOrUpdate() 是 Hibernate 提供的「智能持久化」方法,配合正確的 unsaved-value 策略,能自動判斷對象生命週期,減少手動區分新增/更新的樣板代碼。但需注意 Session 緩存機制,避免同一 Session 中出現相同標識符的多個實例。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved