Spring boot @Cacheable 引入的思考

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

<< SchoolRepository.java >>

@CacheConfig( cacheNames = "school" )
public interface SchoolRepository extends JpaRepository
{
@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 );
}

<< SchoolTest.java >>

@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() );
}

Paste_Image.png

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

Paste_Image.png

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

    @Transactional
public  S save(S entity) {

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

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


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

测试结果:

Paste_Image.png

你可能感兴趣的:(Spring boot @Cacheable 引入的思考)