MyBatis中的缓存机制

MyBatis中的缓存机制

通常的ORM(Object Relational Mapping)框架都会提供缓存功能以减小访问数据库的次数,减轻数据库压力,提升查询效率。MyBatis中有一级和默认实现的二级缓存,并且MyBatis也预留了集成第三方缓存的接口(二级缓存接口的自定义实现)。sql

先经过一段源码来看看mybatis的查询的执行流程。数据库

1> openSqlSession()->getMapper()->query(),mybatis中最终的执行是交给Executor执行器来执行的,Executor接口的实现类中有一个CachingExecutor类(这是mybatis实现的二级缓存)。缓存

2> 执行query方法mybatis

 1 @Override
 2 public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
 3     throws SQLException {
 4   //获取缓存对象
 5   Cache cache = ms.getCache();
 6   if (cache != null) {//存在缓存
 7     //尝试刷新缓存,确保缓存是最新
 8     flushCacheIfRequired(ms);
 9     //若是缓存启用而且该查询没有用到ResultHandler
10     if (ms.isUseCache() && resultHandler == null) {
11       //参数检查
12       ensureNoOutParams(ms, boundSql);
13       @SuppressWarnings("unchecked")
14       //从缓存中读取
15       List<E> list = (List<E>) tcm.getObject(cache, key);
16       if (list == null) {//未命中,调用默认执行器执行query
17         list = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
18         //查询结果放入缓存
19         tcm.putObject(cache, key, list); // issue #578 and #116
20       }
21       return list;
22     }
23   }
24   return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
25 }

 

经过上面一段代码,能够发现如下两个问题:app

  • 首先,你们大概能够猜想出mybatis中一级缓存和二级缓存的优先级顺序了吧?😂没错,在开启二级缓存的状况下会先从二级缓存中读取——>二级缓存未命中的话会调用默认执行器的query方法——>默认执行器再读取本身的一级缓存——>未命中则访问数据库——>查询结果放入缓存。框架

  • 二级缓存是保存在MappedStatement中的,MappedStatement是用来存放咱们的定义DAO层的mapper的信息。一个mapper接口对应一个MappedStatement,那么二级缓存的做用域就是同一mapper下有效。ide


一级缓存:

mybatis 的一级缓存是sqlSession级别的,缓存做用域是在一次数据库会话中有效。一级缓存是持久化缓存(本地缓存)而且是默认开启的,不须要手动开启。ui

为何说一级缓存是Session级别的而且是本地缓存呢?mybatis中每个sqlSession都会对应一个继承自BaseExecutor的Executor(默认是SimipleExecutor)。而BaseExecutor中存在两个PerpetualCache类型的实现Cache接口的对象,见名知意,它就是一个持久化的缓存对象,具体的持久化实现很少赘述(没看😢)。spa

  

为了不脏读,sqlSession执行了DML操做(insert、update、delete),并commit了以后,mybatis会清空当前sqlSession缓存中的全部缓存数据。code


二级缓存

从开头的源码解读能够看出,二级缓存的做用域是同一mpper接口,全部的sqlSession查询结果都会走MapperStatement中的Cache。mybatis中的二级缓存默认是关闭的须要手动开启。

开启mybatis二级缓存的方法:

  • 在mybatis配置文件中添加下面的设置

    <settings>
            <setting name="cacheEnabled" value="true"/>
    </settings>
  • 在须要开启二级缓存的mapper.xml文件中添加下面的配置

    <!-- 当前mapper下全部语句开启二级缓存 -->
    <!-- 也能够在对应的mapper接口上添加@CacheNamespace注解 -->
    <cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>

    具体的执行流程能够看开头的源码解析,不过多赘述

相关文章
相关标签/搜索