一次mybatis缓存

2018-07-10  本文已影响0人  巨子联盟

mybatis缓存分一级和二级
一级缓存在配置文件中配置,分SESSIONSTATEMENT,默认是SESSION缓存,
配置如下:

#开启一级缓存
<setting name="localCacheScope" value="SESSION"/>
#开启一级缓存
<setting name="localCacheScope" value="STATEMENT"/>

今天的问题是开启了<setting name="localCacheScope" value="STATEMENT"/>后就不会有脏读,相当于关闭了一级缓存

毕竟禁用一级缓存不是很好,所以决定研究一下为啥更新之后没有清空一级缓存.
mybatis是在org.apache.ibatis.executor.BaseExecutor执行增删改查操作的.
我们在里面打断点

  @SuppressWarnings("unchecked")
  @Override
  public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
    if (closed) {
      throw new ExecutorException("Executor was closed.");
    }
    if (queryStack == 0 && ms.isFlushCacheRequired()) {
      clearLocalCache();
    }
    List<E> list;
    try {
      queryStack++;
      list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
      if (list != null) {
        handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
      } else {
        list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
      }
    } finally {
      queryStack--;
    }
    if (queryStack == 0) {
      for (DeferredLoad deferredLoad : deferredLoads) {
        deferredLoad.load();
      }
      // issue #601
      deferredLoads.clear();
      if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
        // issue #482
        clearLocalCache();
      }
    }
    return list;
  }

上面代码有两处会触发 清空一级缓存, clearLocalCache();我们发现即使在
XML配置文件中加上了useCache="false"也是无效的,因为这个是控制二级缓存的.

    <select id="querySerialNoToUem"  resultMap="DocAsnSubSerialNo" parameterType="DocAsnSubSerialNo" useCache="false" >
        SELECT T.* 
         FROM  DOC_ASN_SUBSERIALNO T
         WHERE T.UEM_SERIALNO_FLAG = 'N'
            AND ASNNO = #{asnno,jdbcType=VARCHAR}
            and rownum &lt;=500
    </select>

跟踪代码观察到

    if (queryStack == 0 && ms.isFlushCacheRequired()) {
      clearLocalCache();
    }

让这个条件变成true就可以了.默认mybatis的配置flushCache="true"就是等于true,为啥无效呢???
但是我们显式的添加上就有效了.

因为项目中我们用到了通用mapper,我们发现在通用Mapper里面 tk.mybatis.mapper.mapperhelper.MapperTemplate类中

statementBuilder.flushCacheRequired(false);

默认都是将刷新一级缓存设置为 false了.这就是我们刚刚在

    if (queryStack == 0 && ms.isFlushCacheRequired()) {
      clearLocalCache();
    }

处 ms.isFlushCacheRequired() 为 false的原因.所以我们要显示指定一下.

上一篇下一篇

猜你喜欢

热点阅读