在 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无效会出错 | 不清楚状态时用 |