zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    软件架构入门
    深入理解JSCore
    原生开发小程序 和 wepy 、 mpvue, Taro 对比
    安装淘宝npm(cnpm)
    CSS预处理器—Sass、LESS和Stylus
    PHP和java比较
    DevOps 在公司项目中的实践落地
    Facebook的React Native之所以能打败谷歌的原因有7个(ReactNative vs Flutter)
    Android 9.0新特性
    主流前端框架对比:Vue.js , React, Angular.js
  • 原文地址:https://www.cnblogs.com/wq-9/p/14277095.html
Copyright © 2011-2022 走看看