@GetMapping("/get")
public Student1 get() {
Optional<Student1> byMobile = studentRepository.findByMobile("19912345678");
byMobile.get().setAge(26);
studentRepository.save(byMobile.get());
return studentRepository.findByMobile("19912345678");;
}
如上代码所示,先查询指定手机的纪录,然后修改该对象的年纪,然后再保存该对象,最后再查询该对象,但是返回的竟然还是修改前的年纪16,不是最新修改的年纪26。
解决方案1:配置spring.jpa.open-in-view: false
/** * Register OpenEntityManagerInViewInterceptor. Binds a JPA EntityManager to the * thread for the entire processing of the request. */ private Boolean openInView;
OpenEntityManagerInViewInterceptor登记。将JPA EntityManager绑定到线程的整个处理请求。
可以看到如果我们没有配置该属性,启动时会warn提示未配置会使用默认值。
解决方案2:@Modifying(clearAutomatically = true)
@Modifying(clearAutomatically = true)
@Query(value = "update t_employee a set a.age = :age where a.id = :id", nativeQuery = true) int updateAgeById(int age, int id);
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Documentedpublic @interface Modifying {
boolean flushAutomatically() default false;
boolean clearAutomatically() default false;
}
@Modifying,进入这个注解,我们能看到,它是指可以清除底层持久化上下文,即entityManager这个类;
Jpa底层实现会有一级缓存,也就是在更新完数据库后,如果后面去用这个对象,你再去查这个对象,这个对象是在一级缓存,
但是并没有跟数据库同步,此时使用clearAutomatically=true,
就会刷新Hibernate的一级缓存,否则在同一接口中,更新一个对象,接着查询这个对象,
那么查出来的这个对象还是之前的没有更新前的状态。