• 聊聊Mybatis的Executor之CachingExecutor


    聊聊Mybatis的Executor之CachingExecutor
    CachingExecutor

    先看一下CachingExecutor类:

    public class CachingExecutor implements Executor {
    
      private final Executor delegate;
    
      @Override
      public int update(MappedStatement ms, Object parameterObject) throws SQLException {
        flushCacheIfRequired(ms);
        return delegate.update(ms, parameterObject);
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    CachingExecutor的成员变量有个Executor实例,这显然是个 装饰器模式 ,这的类就是在其他Executor实例的方法进行了flushCacheIfRequired(),也就是刷新缓存,所以这个类在其他类上添加了缓存的功能,从query()方法中也能看出先查找缓存,缓存没有再进行调用Executor实例的query()进行数据的查询
    二级缓存

    这里的缓存是二级缓存,我们通过它的query()方法具体看一下二级缓存的逻辑:

    @Override
      public  List query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
          throws SQLException {
        Cache cache = ms.getCache();
        if (cache != null) {
          flushCacheIfRequired(ms);
          if (ms.isUseCache() && resultHandler == null) {
            ensureNoOutParams(ms, boundSql);
            @SuppressWarnings("unchecked")
            List list = (List) tcm.getObject(cache, key);
            if (list == null) {
              list = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
              tcm.putObject(cache, key, list);
            }
            return list;
          }
        }
        return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    获取二级缓存对象
    如果对象不为空,表明开启了二级缓存,根据select标签的flushCache配置决定是否清空二级缓存,将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:false。
    然后检测select标签的useCache 属性,将其设置为 true 后,将会导致本条语句的结果被二级缓存缓存起来,默认值:对 select 元素为 true
    调用TransactionalCacheManager的getObject()方法获取二级缓存
    如果二级缓存为空就查询数据库,并把结果写入缓存中
    最后返回list
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    从代码中可以看出TransactionalCacheManager管理着缓存,他有个成员变量是map集合:Map transactionalCaches = new HashMap<>();

    获取缓存的方法是先获取到map中的TransactionalCache对象,再调用TransactionalCache的getObject(key)方法,那我们需要重点看一下TransactionalCache类了
    事务缓存类TransactionalCache

    TransactionalCache实现了Cache接口,用来记录事务中的二级缓存的数据

    public class TransactionalCache implements Cache {
      private final Map entriesToAddOnCommit;
    
      @Override
      public void putObject(Object key, Object object) {
        entriesToAddOnCommit.put(key, object);
      }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    entriesToAddOnCommit是用来赞存二级缓存中的数据的,也是说在调用查询方法的时候,只是把二级缓存的数据缓存到entriesToAddOnCommit这个map集合中,在调用CachingExecutor的commit()方法的时候,才会遍历集合把数据保存到二级缓存Cache中

    @Override
      public void commit(boolean required) throws SQLException {
        delegate.commit(required);
        tcm.commit();
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    总结

    对于Executor的CachingExecutor实现类就说这么多,它的作用就是实现二级缓存的,由它的成员变量TransactionalCacheManager来进行管理二级缓存的数据,值得一提的是,二级缓存数据真正的提交是在事务提交之后进行,这能防止出现脏读现象

  • 相关阅读:
    运维困局下确保系统稳定的可行性
    一天梳理完react面试高频知识点
    java计算机毕业设计基于安卓Android/微信小程序的智慧养老院管理系统
    【无标题】
    ChatGPT魔法背后的原理:如何做到词语接龙式输出?
    PyTorch学习(三)
    在服务器上搭建pulseaudio的运行环境,指定其运行目录、状态目录和模块目录
    浅谈Linux PMIC驱动(一)
    【数据结构与算法】常见排序算法(Sorting Algorithm)
    简谈Spring Boot3.0升级后的踩坑之旅,另附解决方案!
  • 原文地址:https://blog.csdn.net/band_mmbx/article/details/126485203