mybatis-缓存模块说明

关于mybatis缓存采用装饰器设计模式;设计到一级缓存和二级缓存;
类模块位置:org.apache.ibatis.cache
核心类如下:
- Cache: Cache 接口是缓存模块的核心接口,定义了缓存的基本操作;
- PerpetualCache:在缓存模块中扮演ConcreteComponent 角色,使用 HashMap来实现 cache 的相关操作;(一级缓存使用该类)
- BlockingCache:阻塞版本的缓存装饰器,保证只有一个线程到数据库去查找指定的 key 对应的数据;


 

 一级缓存

一级缓存默认会启用,想要关闭一级缓存可以在 select 标签上配置 flushCache=“true”

一级缓存存在于 SqlSession 的生命周期中,在同一个 SqlSession 中查询时, MyBatis 会把执

行的方法和参数通过算法生成缓存的键值,将键值和查询结果存入一个 Map 对象中。如果同一个 SqlSession 中执行的方法和参数完全一致,那么通过算法会生成相同的键值,当Map 缓存对象中己经存在该键值时,则会返回缓存中的对象;

任何的 INSERT 、 UPDATE 、DELETE 操作都会清空一级缓存;

二级缓存

二级缓存也叫应用缓存,存在于 SqlSessionFactory 的生命周期中,可以理解为跨 sqlSession;

缓存是以 namespace 为单位的,不同 namespace 下的操作互不影响。在 MyBatis 的核心配置

文件中 cacheEnabled 参数是二级缓存的全局开关,默认值是 true,如果把这个参数设置为

false,即使有后面的二级缓存配置,也不会生效;要开启二级缓存,你需要在你的 SQL Mapper 文件中添加配置

<cache eviction=“LRU" flushInterval="60000" size="512" readOnly="true"/>

 

开发建议: 使用二级缓存容易出现脏读,建议避免使用二级缓存,在业务层使用可控制的缓存代替更好;

重点说明:二级缓存的并发问题;默认实现了SynchronizedCache 如下截图:

调用顺序是先查二级缓存,再查一级缓存

代码实现类:xml

 

 

 代码调用入口CacheBuilder

  private Cache setStandardDecorators(Cache cache) {
    try {
      MetaObject metaCache = SystemMetaObject.forObject(cache);
      if (size != null && metaCache.hasSetter("size")) {//如果有size属性设置最大元素
        metaCache.setValue("size", size);
      }
      if (clearInterval != null) {//设置定时清空
        cache = new ScheduledCache(cache);
        ((ScheduledCache) cache).setClearInterval(clearInterval);
      }
      if (readWrite) {//设置读写属性
        cache = new SerializedCache(cache);
      }
      cache = new LoggingCache(cache);//默认加上日志能力
      cache = new SynchronizedCache(cache);//默认加上同步能力
      if (blocking) {//根据配置加上阻塞能力
        cache = new BlockingCache(cache);
      }
      return cache;
    } catch (Exception e) {
      throw new CacheException("Error building standard cache decorators.  Cause: " + e, e);
    }
  }

 

  • 二级缓存入口: org.apache.ibatis.executor.CachingExecutor.query(MappedStatement, Object, RowBounds, ResultHandler)
  • 一级缓存入口: org.apache.ibatis.executor.BaseExecutor.query(MappedStatement, Object, RowBounds, ResultHandler)
posted @ 2021-11-13 23:51  cqzaier  阅读(40)  评论(0)    收藏  举报