理解Hibernate持久化操作的前提是掌握對象的三種狀態:
| 方法 | 適用狀態 | SQL操作 | ID生成時機 | 事務邊界行為 |
|---|---|---|---|---|
| save() | 瞬態 | INSERT | 立即執行 | 無事務也執行INSERT |
| persist() | 瞬態 | INSERT | 可延遲至flush | 事務外不執行INSERT |
| update() | 脫管態 | UPDATE | 不適用 | 立即關聯Session |
| merge() | 脫管態/瞬態 | INSERT/UPDATE | 視情況而定 | 返回新持久態對象 |
| saveOrUpdate() | 瞬態/脫管態 | INSERT/UPDATE | 視情況而定 | 智能判斷執行 |
| lock() | 脫管態(未修改) | 無 | 不適用 | 僅關聯Session |
// save: 需立即返回ID,故無事務也執行INSERT
Session session = factory.openSession();
User user = new User("John");
Serializable id = session.save(user); // 立即執行INSERT
session.close();
// persist: 事務外不執行INSERT,適合長會話模式
Session session = factory.openSession();
User user = new User("John");
session.persist(user); // 僅標記為持久化,不立即執行SQL
// ... 後續在事務中flush時才真正執行INSERT
Transaction tx = session.beginTransaction();
tx.commit(); // 此處執行INSERT
// update場景
User detachedUser = ...; // 脫管對象
session.update(detachedUser); // detachedUser變為持久態
detachedUser.setName("New"); // 直接修改生效
// merge場景
User detachedUser = ...;
User persistentUser = (User)session.merge(detachedUser); // 返回新持久態對象
persistentUser.setName("New"); // 需操作返回的對象
// detachedUser仍為脫管態
內部判斷流程:
持久態對象修改無需調用update(),Hibernate在以下時機自動flush:
session.flush()// lock使用模式
User detachedUser = ...;
session.lock(detachedUser, LockMode.NONE); // 重新關聯
detachedUser.setName("Modified"); // 修改持久態對象
session.flush(); // 同步修改
persist()(JPA標準),事務邊界清晰merge()更安全(避免非唯一對象異常),update()性能略優saveOrUpdate()自動路由lock()或session.buildLockRequest(LockMode.NONE).lock(entity)