提问者:小点点

spring data jpa saveandflush方法


我确实理解JpaRepository Spring Data jpa类的方法save和方法saveAndFlush之间的区别。按照我的理解,save方法将只在事务结束时运行并提交sql,而saveAndFlush方法将通过运行sql语句而不提交它来使持久性上下文与数据库同步。下面是一个示例代码,我想在那里体验它,请回顾它。

这是更新的存储库类

@Repository
public interface ClassRepository extends JpaRepository<ClassA, Long> {

    @Modifying(clearAutomatically = true)
    @Query(value = "UPDATE class e SET e.class_name = ? WHERE e.employee_id = ?", nativeQuery = true)
    int updateClassNative(String className, String empId);

}

这是我测试方法的测试用例

    @Test
    void saveAndUpdateWithFlushJPA() {
        ClassA classA = ClassA.builder().className("Test").employeeId("S0810").build();

    this.classRepository.save(classA);
    int size = this.classRepository.updateClassNative("TestQ", "S0810");
    assertThat(size).isEqualTo(1);
}

阿什利


共1个答案

匿名用户

您的测试场景的问题是,JPA总是在执行本机查询之前刷新持久性上下文(这也是JPQL查询的默认行为,尽管它可以被覆盖)。其基本原理是,查询应该报告反映当前工作单元中已经进行的更改的状态。

要查看save/saveandflush之间的区别,您可以使用以下测试用例来代替:

@Repository
public interface ClassRepository extends JpaRepository<ClassA, Long> {

    @Query("SELECT COUNT(c.id) FROM ClassA c")
    @QueryHints({
        @QueryHint(name = org.hibernate.annotations.QueryHints.FLUSH_MODE, value = "COMMIT")
    })
    int countClassAEntities();
}

@Test
@Transactional
void saveAndUpdate() {
    int initialCount = classRepository.countClassAEntities(); 
    ClassA classA = ClassA.builder().className("Test").employeeId("S0810").build();
    classRepository.save(classA);
    int finalCount = classRepository.countClassAEntities();
    assertEquals(initialCount, finalCount);
}

@Test
@Transactional
void saveAndUpdateWithFlush() {
    int initialCount = classRepository.countClassAEntities(); 
    ClassA classA = ClassA.builder().className("Test").employeeId("S0810").build();
    classRepository.saveAndFlush(classA);
    int finalCount = classRepository.countClassAEntities();
    assertEquals(initialCount + 1, finalCount);
}

在上面的设置中,count查询将刷新模式设置为commit,这意味着执行查询不会触发刷新。如果使用默认的repository.count()方法,则第一个测试用例将失败,因为默认情况下,刷新模式设置为auto