我确实理解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);
}
阿什利
您的测试场景的问题是,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
。