• springboot +ssm中mybatis缓存问题


      最近操作springboot+ssm时,查询日志,根据日志表查某个业务表的数据时,其实也就是重复查询某一条业务数据。

    一般查询业务表的数据,会把id查询出name 字符反给前端。对一条数据的多次查询,第一查询时,没问题,第二次查询(同一条数据),直接反了name, 没有根据id再查name。 其实这也就是mybatis的一级缓存。

     

    题外话:

    1.一级缓存只有在开启了数据库事物【@EnableTransactionManagement】并且处于一个被事物标注的方法下【直接或间接】才会生效。

    2.禁用一级缓存:mybatis没有提供一级缓存的启用、禁用开关,但在Mapper文件对应的语句中增加flushCache="true"可以达到实际禁用一级缓存的效果,一般同时还会加上useCache="false",以便关闭二级缓存;下面讨论使用springboot配置的方式控制一级缓存。

    一、在springboot下的配置

    MyBatis 一级缓存(MyBaits 称其为 Local Cache)无法关闭,但是有两种级别可选:

    A.session

            在同一个 sqlSession 内,对同样的查询将不再查询数据库,直接从缓存中获取。

    mybatis:
      configuration:
        cache-enabled: false  #禁用二级缓存
        local-cache-scope: session  #一级缓存指定为session级别
    B.statement
    mybatis:
      configuration:
        cache-enabled: false #禁用二级缓存
        local-cache-scope: statement #一级缓存指定为statement级别
     

            每次查询结束都会清掉一级缓存,实际效果就是禁用了一级缓存;

    二、不同设置方式在数据库事物中的表现

    1.  
      @Transactional(propagation = Propagation.REQUIRED)
    2.  
      public List<Users> getUsers() {
    3.  
      List<Users> usersList = usersMapper.selectByExample(new UsersExample()); #1
    4.  
      usersList = usersMapper.selectByExample(new UsersExample()); #2
    5.  
      return usersList;
    6.  
      }

    A.一级缓存级别设置为session

    在代码中1处,通过日志观察,打印出sql语句,未走缓存【此时缓存数据还不存在】;

    在执行2处语句之前,通过数据库工具修改数据库记录并提交,继续执行程序后,通过日志观察,未打印出sql语句,获取的数据未体现出通过工具修改数据的变化,说明使用的是缓存中的数据;

    B.一级缓存级别设置为statement

    在代码中1处,通过日志观察,打印出sql语句,未走缓存【此时缓存数据还不存在】;

    在执行2处语句之前,通过数据库工具修改数据库记录并提交,继续执行程序后,通过日志观察,打印出sql语句,且获取的数据也体现出通过工具修改数据的变化,说明未使用缓存中的数据;

    结论:通过将一级缓存级别设置为statement,可以达到禁用一级缓存的效果。

    @Transactional(propagation = Propagation.REQUIRED)
    public List<Users> getUsers() {
        List<Users> usersList = usersMapper.selectByExample(new UsersExample());  
        usersList = usersMapper.selectByExample(new UsersExample());  
        return usersList;
    }

    #下面的代码属于usersServer

    @Transactional(propagation = Propagation.REQUIRED)
    public List<Users> getUsers() {
        List<Users> usersList = usersMapper.selectByExample(new UsersExample());  #1
        usersList = usersServer.getUsersList();
        return usersList;
    }

    观察到的结果与上面的一致。

    结论:同上,同时证明了嵌套事物NESTED本质上与上层事物处于一个相同的事物中。

    将代码3处事物配置调整成REQUIRES_NEW,重做之前的实验;

    观察到的结果:在一级缓存级别为session与statement时,现象一致,带执行代码2处,均打印SQL语句,并且体现出了手动修改数据库记录的效果;

    结论:REQUIRES_NEW确实重新起了一个新的事物,与上层事物没有关系。

    终极结论:

    1.将mybatis一级缓存级别设置为statement可以事实上达到禁用一级缓存的效果;

    2.启用mybatis一级缓存,将级别设置为session【或不做任何设置,mybaits默认就是这个级别】

    https://blog.csdn.net/nongyeting/article/details/106408985

  • 相关阅读:
    UVa OJ 148 Anagram checker (回文构词检测)
    UVa OJ 134 LoglanA Logical Language (Loglan逻辑语言)
    平面内两条线段的位置关系(相交)判定与交点求解
    UVa OJ 130 Roman Roulette (罗马轮盘赌)
    UVa OJ 135 No Rectangles (没有矩形)
    混合函数继承方式构造函数
    html5基础(第一天)
    js中substr,substring,indexOf,lastIndexOf,split等的用法
    css的textindent属性实现段落第一行缩进
    普通的css普通的描边字
  • 原文地址:https://www.cnblogs.com/wq-9/p/14277095.html
Copyright © 2020-2023  润新知