在Hibernate中,save()
和saveOrUpdate()
都是用于持久化对象的方法,但它们的适用场景和行为有显著差异:
1. save()
方法
-
核心行为:
- 仅适用于瞬时态(Transient)对象(即新创建、未与Session关联的对象)。
- 会立即为对象分配一个标识符(ID),并计划在事务提交时执行INSERT操作。
- 若尝试对已持久化(Persistent)或游离态(Detached)对象调用
save()
,会抛出异常。
-
返回值:
返回生成的Serializable
类型的主键ID。 -
典型场景:
User user = new User(); // 瞬时态对象 Serializable id = session.save(user); // 执行INSERT,返回ID
2. saveOrUpdate()
方法
-
核心行为:
- 智能判断对象状态:
- 若对象为瞬时态:执行INSERT操作(类似
save()
)。 - 若对象为游离态:执行UPDATE操作(更新数据库记录)。
- 若对象已为持久态:忽略操作(无需重复保存)。
- 若对象为瞬时态:执行INSERT操作(类似
- 不会返回主键ID(无返回值,
void
)。
- 智能判断对象状态:
-
典型场景:
User user1 = new User(); // 瞬时态 session.saveOrUpdate(user1); // 执行INSERTUser user2 = session.get(User.class, 1L); // 持久态 session.evict(user2); // 转为游离态 user2.setName("NewName"); session.saveOrUpdate(user2); // 执行UPDATE
3. 关键区别总结
特性 | save() | saveOrUpdate() |
---|---|---|
适用对象状态 | 仅瞬时态 | 瞬时态、游离态 |
返回值 | 返回主键ID | 无返回值(void) |
重复调用 | 对同一对象重复调用会引发异常 | 对同一对象可安全重复调用 |
数据库操作 | 总是INSERT | 可能INSERT或UPDATE |
4. 如何选择?
-
使用
save()
:
明确需要插入新记录且无需处理游离态对象时(如严格的新增操作)。 -
使用
saveOrUpdate()
:
不确定对象状态(如从表单接收的数据可能对应新增或修改),或需要统一处理插入/更新逻辑时。
⚠️ 注意:
- 对游离态对象调用
save()
会抛出TransientObjectException
。saveOrUpdate()
可能因版本冲突(如乐观锁)抛出StaleObjectStateException
。