美文网首页
一次mybatis缓存

一次mybatis缓存

作者: 巨子联盟 | 来源:发表于2018-07-10 09:18 被阅读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的原因.所以我们要显示指定一下.

    相关文章

      网友评论

          本文标题:一次mybatis缓存

          本文链接:https://www.haomeiwen.com/subject/srtayftx.html