Hibernate 中,save()persist()update()merge()saveOrUpdate() 都用于操作实体对象的持久化状态,但它们的行为和使用场景各不相同。下面是它们的详细对比:

一、save()

  • 作用:将一个瞬时(transient)对象保存到数据库中,返回生成的主键 ID。
  • 状态要求:只能用于瞬时对象。
  • 是否立即插入:是(会立即执行 INSERT 语句)。
  • 返回值:返回生成的主键值(Serializable)。
  • 特点:可以在没有开启事务的情况下调用,但不推荐。

适用场景:需要立即插入数据并获取主键。

二、persist()

  • 作用:也用于将瞬时对象持久化到数据库
  • 状态要求:只能用于瞬时对象。
  • 是否立即插入:否(需要事务提交或 flush() 后才执行 INSERT)。
  • 返回值void,不返回主键。
  • 特点:是 JPA 标准方法,推荐在 JPA 环境下使用。

适用场景:你在使用 JPA 规范,希望更安全、更规范地保存数据。

三、update()

  • 作用:将一个脱管(detached)对象重新关联到 Hibernate 的持久化上下文,并更新数据库。
  • 状态要求:只能用于脱管对象(detached)。
  • 是否立即更新:是,或在事务提交时。
  • 返回值:无。
  • 注意事项:如果该对象在当前 Session 中已有同一 ID 的持久化对象,会抛出异常(NonUniqueObjectException)。

适用场景:你已经有一个从数据库查询出来、修改过的对象,要将修改后的值更新回数据库。

四、merge()

  • 作用:将一个脱管对象的状态合并到持久化上下文中,返回一个新的持久化对象。
  • 状态要求:用于脱管对象。
  • 是否立即更新:在事务提交或 flush() 时。
  • 返回值:返回一个新的持久化对象。
  • 特点:更安全,不会抛出对象重复异常。

适用场景:不知道当前对象是不是在 Session 中,或者你不确定状态,建议使用 merge()

五、saveOrUpdate()

  • 作用:根据对象是否有 ID 来决定是执行 save() 还是 update()
  • 状态要求:可用于瞬时或脱管对象。
  • 是否立即执行:是。
  • 返回值:无。
  • 注意事项:如果 ID 存在且数据库中无对应记录,可能会抛异常。

适用场景:不确定对象状态(是新对象还是旧对象),但希望自动决定新增或更新。

总结对比表:

方法适用状态是否立即执行是否返回主键抛异常风险推荐使用场景
save()瞬时获取主键、非 JPA 环境
persist()瞬时JPA 标准、推荐方式
update()脱管对象冲突脱管对象需重新管理
merge()脱管是(返回新对象)少(更安全)脱管对象、不确定状态
saveOrUpdate()瞬时/脱管ID无效会出错不清楚状态时用