Mybatis缓存体系:一级缓存

一 、概要

一级缓存是会话级别的,也就是一个SqlSession里的,不同会话的一级缓存是互相隔离,不可见的,当会话结束,一级缓存也就被销毁。
一级缓存维护在BaseExecutor类中:

二 、一级缓存开启和关闭

一级缓存默认是开启的。
如何关闭呢?
一级缓存是没有关闭配置的,也就是说代码中都会设置一级缓存,我们配置的关闭缓存实际是代码中清空一级缓存而已,看源码:
BaseExecutor#query

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()) {
      //flushCacheRequired如果设置为true,则清空一级缓存
      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();
      }
      deferredLoads.clear();
      if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
        //如果localCacheScope配置的不是session级别则清空一级缓存
        clearLocalCache();
      }
    }
    return list;
  }
  
    //查询数据库
    private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
        List<E> list;
        localCache.putObject(key, EXECUTION_PLACEHOLDER);
        try {
          list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
        } finally {
          localCache.removeObject(key);
        }
        //把结果放到一级缓存
        localCache.putObject(key, list);
        if (ms.getStatementType() == StatementType.CALLABLE) {
          localOutputParameterCache.putObject(key, parameter);
        }
        return list;
  }

可以看到每次查询数据库后都会把数据放入到一级缓存中,如果localCacheScope设置的不是session而是statement,那么则会清空一级缓存。如果flushCache设置为true,也会清空缓存,去查数据库。

三 、命中条件

1 同一个SqlSession

因为一级缓存是会话级别,这个没啥好说的。

2 localCacheScope设置的值为SESSION


如果不是SESSION则第一次查询则清空缓存,第二次查询就不会命中缓存。

3 flushCache没有设置为true

4 相同的statementId

StatementId就是指的同一个Mapper.xml文件,同一个id,哪怕sql一样,如果方法名不一样,也不会命中。

5 sql的参数一样

6 未执行update操作

mybatis中update操作指的是update、delete、insert,如果同一个会话里有update操作,则会删除一级缓存。
BaseExecutor#updat()

四 、Spring整合Mybatis一级缓存会失效?

spring整合后,每次查询,都会新建一个会话,所以一级缓存不会命中。如果开启事务的化,就会用的同一个会话,会命中一级缓存。

五 、和二级缓存关系

二级缓存是应用级别的,当查询时候,是先查询二级缓存,如果未命中则查询一级缓存,一级缓存未命中,则查询数据库。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值