Spring Data JPA中的save和saveAndFlush之间的区别

167

我正在尝试通过测试 JpaRepository 上的一些 CRUD 操作来学习 spring data JPA。

我遇到了两个方法 savesaveAndFlush。 我不明白这两者之间的区别。在调用 save 时,我的更改也被保存到数据库中,那么使用 saveAndFlush 的意义是什么。

5个回答

180
在使用saveAndFlush时,更改会立即刷新到数据库中。而使用save则不一定如此,更改有可能只停留在内存中,直到发布flushcommit命令为止。
但需要注意的是,即使您在事务中刷新更改但未提交它们,这些更改对外部事务仍然不可见,直到在该事务中提交为止。
在您的情况下,您可能使用某种事务机制,如果一切顺利,将为您发布commit命令。

51
如果一个事务的隔离级别为READ_UNCOMMITTED,则它将看到其他事务已经刷新但尚未提交的内容,但这些内容直到此事务提交后才会对外部事务可见。 - Gab是好人
1
但是,在我的项目中,我使用save()、saveAll()方法,它们在没有显式调用commit或flush的情况下持久化到数据库中。那么为什么我应该选择saveAndFlush呢?flush模式和其他一些东西都是默认模式。 - Satish Patro
1
P Satish Patro,saveAndFlush() 用于立即刷新。如果您使用 save(),则刷新操作将由 JPA 在稍后处理。 - apr

53

根据您使用的 Hibernate 刷新模式 (默认为 AUTO),save 可能会直接将更改写入数据库,也可能不会。当您调用 saveAndFlush 时,您正在强制同步模型状态与数据库。

如果您使用 AUTO 刷新模式,并使用应用程序先保存数据,然后再选择数据,那么在 save()saveAndFlush() 之间的行为上,您将看不到任何差异,因为选择操作首先触发了刷新。请参见文档


抱歉,如果我保存一个实体并再次保存相同的实体,您的意思是使用“save”时第二个命令不会因重复而引发异常,是吗? - azerafati
3
是的,我的理解是调用 save 的操作具有幂等性。有关更多详细信息,请参阅此 线程 - Ralf

5

这两种方法都用于将实体保存到数据库。刷新是将持久化上下文的状态与底层数据库同步的过程。

使用saveAndFlush方法时,数据会立即刷新到数据库中。如果使用save方法,我们需要明确调用flush()方法才能进行刷新。 使用flush可以在事务提交之前的同一步骤中读取已保存的更改。因此,如果不需要提交,仍然可以进行回滚操作


1
"save"方法用于将实体保存到数据库中。当调用"save"方法时,实体首先被持久化到数据库的事务缓冲区中,然后在事务提交时,实体被保存到数据库中。"save"方法返回保存的实体。
另一方面,"save and flush"方法与"save"方法做的事情相同,但还会强制数据库立即将待定更改写入磁盘。这在需要确保数据立即持久化到数据库而不是等待事务提交的情况下非常有用。
总之,在Spring Data中,"save"和"save and flush"的主要区别在于后者立即将待定更改写入数据库,而前者则等待事务提交后再执行。
如果您想在同一个事务中保存新实体并使用其ID,应该先使用"save"方法,然后调用"flush"方法。
当调用"save"方法时,实体被持久化到事务缓冲区,并且为实体分配了临时ID。这个ID由底层持久化框架生成,不是最终保存到数据库时分配给实体的ID。

通过调用"flush"方法,您可以强制底层持久化框架立即将待处理的更改写入数据库。这将导致实体的临时ID被数据库分配的最终ID替换。

一旦调用了"flush"方法,在同一事务中您可以安全地使用新保存实体的ID。


0
在Spring Data Jpa中,save()方法允许我们将实体保存到数据库中。它属于Spring Data定义的CrudRepository接口。
当我们使用save()方法时,与保存操作相关的数据只有在显式调用flush()或commit()方法之后才会刷新到数据库中。
例如,让我们创建一个实体和JPA存储库。
@Data
@Entity
public class User{

    @Id
    private Long id;
    private String name;
}


public interface UserRepository extends JpaRepository<User, Long> {
}

然后可以像这样使用save()方法,

userRepository.save(new User(1L, "Geeth"));

但是saveAndFlush()方法与save()不同。 saveAndFlush()方法在执行期间立即刷新数据。此方法属于Spring Data JPA的JpaRepository接口。您可以按以下方式使用它。

userRepository.saveAndFlush(new User(2L, "Sam"));

通常,我们在业务逻辑需要在同一事务中稍后读取保存的更改但在提交之前使用此方法。
例如,想象一个场景,我们必须执行一个存储过程,该存储过程期望实体的属性,我们将要保存。在这种情况下,save() 方法不起作用,因为更改与 DB 不同步,存储过程不知道更改。saveAndFlush() 方法非常适合这种情况。

这几乎是从 https://www.baeldung.com/spring-data-jpa-save-saveandflush 直接复制的。至少应该给出应有的归属说明… - Attila

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接