美文网首页
Spring boot @Cacheable 引入的思考

Spring boot @Cacheable 引入的思考

作者: TTTTTriM | 来源:发表于2017-01-11 16:36 被阅读1341次

刚刚关于@Cacheable 标签的测试用例,陷入一个很简单的陷阱!

<< SchoolRepository.java >>
<code>
@CacheConfig( cacheNames = "school" )
public interface SchoolRepository extends JpaRepository<School, Long>
{
@Cacheable
School findByName( String name );
School findByNameAndTotalStudents( String name, Integer totalCount );
@Query( "from School s where s.name=:name" )
School findSchool( @Param( "name" ) String name );
@Modifying
@Query( "update School s set s.totalStudents = ?2 where s.name = ?1" )
int updateSchool( String name, int total );
}
</code>

<< SchoolTest.java >>
<code>
@Test
@Transactional
@Rollback( true )
public void schoolCacheTest()
{
schoolRepository.save( new School( "AAA", 10 ) );
School sch1 = schoolRepository.findByName( "AAA" );
System.out.println( "The first query -> " + sch1.getTotalStudents() );
schoolRepository.updateSchool( "AAA", 1 );
School sch2 = schoolRepository.findByName( "AAA" );
System.out.println( "The second query -> " + sch2.getTotalStudents() );
}
</code>

Paste_Image.png

@Cacheable 本身测试没有任何问题,schoolRepository.findByName 没有第二次打印查询SQL,后面突发奇想的想测试一下更新之后数据的结果, 加入了schoolRepository.updateSchool,去掉了@Cacheable,发现数据还是没有更新。

Paste_Image.png

而后细想起来@Transactional,这么偌大的一个事务,导致更新的数据还未commit,肯定是这样。
但是 schoolRepository.save 怎么能插入数据呢!
马上去看JPA源码:

    @Transactional
public <S extends T> S save(S entity) {

    if (entityInformation.isNew(entity)) {
        em.persist(entity);
        return entity;
    } else {
        return em.merge(entity);
    }
}

save方法自带@Transactional,继承上层方法的事务进行提交,导致插入可以,更新数据无法提交导致查询的为旧数据。OK,进一步验证,将updateSchool方法加入事务。

<code>
@Transactional
@Modifying
@Query( "update School s set s.totalStudents = ?2 where s.name = ?1" )
int updateByName(String name, Integer total);
</code>

测试结果:

Paste_Image.png

相关文章

网友评论

      本文标题:Spring boot @Cacheable 引入的思考

      本文链接:https://www.haomeiwen.com/subject/bzgxhttx.html