mybatis体系结构,终于最后一篇了

二级缓存

主要内容:

mybatis体系结构,终于最后一篇了_第1张图片

二级缓存构建在一级缓存之上,在收到查询请求时,MyBatis 首先会查询二级缓存。若二级缓存未命中,再去查询一级缓存。与一级缓存不同,二级缓存和具体的命名空间绑定,一级缓存则是和 SqlSession 绑定。

在按照 MyBatis 规范使用 SqlSession 的情况下,一级缓存不存在并发问题。二级缓存则不然,二级缓存可在多个命名空间间共享。这种情况下,会存在并发问题,因此需要针对性去处理。除了并发问题,二级缓存还存在事务问题。

二级缓存如何开启?

配置项

`
  
    
  


`

cacheEnabled=true表示二级缓存可用,但是要开启话,需要在Mapper.xml内配置。

`
或者 简单方式

`

对配置项属性说明:

  • flushInterval="60000",间隔60秒清空缓存,这个间隔60秒,是被动触发的,而不是定时器轮询的。
  • size=512,表示队列最大512个长度,大于则移除队列最前面的元素,这里的长度指的是CacheKey的个数,默认为1024。
  • readOnly="true",表示任何获取对象的操作,都将返回同一实例对象。如果readOnly="false",则每次返回该对象的拷贝对象,简单说就是序列化复制一份返回。
  • eviction:缓存会使用默认的Least Recently Used(LRU,最近最少使用的)算法来收回。FIFO:First In First Out先进先出队列。

在Configuration类的newExecutor方法中是否开启二级缓存

`public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
    executorType = executorType == null ? defaultExecutorType : executorType;
    executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
    Executor executor;
    if (ExecutorType.BATCH == executorType) {
      executor = new BatchExecutor(this, transaction);
    } else if (ExecutorType.REUSE == executorType) {
      executor = new ReuseExecutor(this, transaction);
    } else {
      executor = new SimpleExecutor(this, transaction);
    }
      //是否开启二级缓存
    if (cacheEnabled) {
      executor = new CachingExecutor(executor);
    }
    executor = (Executor) interceptorChain.pluginAll(executor);
    return executor;
  }
`

二级缓存通过CachingExecutor来实现的,原理是缓存里存在,就返回,不存在就调用Executor ,如果一级缓存未关闭,则先查一级缓存,不存在,再到数据库中查询。

下面使用一张图来表示:

mybatis体系结构,终于最后一篇了_第2张图片

下面是源码:

`@Override
public  List query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
    // 获得 BoundSql 对象
    BoundSql boundSql = ms.getBoundSql(parameterObject);
    // 创建 CacheKey 对象
    CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
    // 查询
    return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
@Override
public  List query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
            throws SQLException {
    // 调用 MappedStatement#getCache() 方法,获得 Cache 对象,
    //即当前 MappedStatement 对象的二级缓存。
    Cache cache = ms.getCache();
    if (cache != null) { // <2>
        // 如果需要清空缓存,则进行清空
        flushCacheIfRequired(ms);
        //当 MappedStatement#isUseCache() 方法,返回 true 时,才使用二级缓存。默认开启。
        //可通过@Options(useCache = false) 或