Mybatis学习笔记-二级缓存

来源:互联网 发布:java直播系统源码 编辑:程序博客网 时间:2024/05/16 09:04

~
缓存是提供应用系统性能的重要手段,前面已经介绍过Mybatis是一级缓存,与一级缓存不同的是,二级缓存的作用范围扩大到了应用级别,并且可以比一级缓存更细粒度的对二级缓存的应用进行配置。下面就详细叙述一下Mybatis的二级缓存实现。

  • 二级缓存的工作流程
    不多说,先上图,图解是攻城狮最好的朋友^_^…

    这里写图片描述

    前面在叙述一级缓存的时候已经说过,一级缓存是一块放在Executor中的map内存块。试想一下,如果二级缓存也是Executor中的内存块可以可以呢?…… 当然不可以!为啥?因为二级缓存要支持细粒度的配置,并且是否应用二级缓存也是用户说了算。

    二级缓存的工作流程是这样的:
    开启一个回话时,mybatis会检查在核心配置文件中是否配置<setting name="cacheEnabled" value="true"/>,如果配置,则Mybatis在创建对象时,会创建一个CachingExecutor,该类是Executor的包装类,mybatis利用装饰设计模式对Exector进行了缓存支持的增强。

 public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {    Cache cache = ms.getCache();    if (cache != null) {      flushCacheIfRequired(ms);      if (ms.isUseCache() && resultHandler == null) {         ensureNoOutParams(ms, key, parameterObject, boundSql);        if (!dirty) {          cache.getReadWriteLock().readLock().lock();          try {            @SuppressWarnings("unchecked")            List<E> cachedList = (List<E>) cache.getObject(key);            if (cachedList != null) return cachedList;          } finally {            cache.getReadWriteLock().readLock().unlock();          }        }        List<E> list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);        tcm.putObject(cache, key, list); // issue #578. Query must be not synchronized to prevent deadlocks        return list;      }    }    return delegate.<E>query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);  }

以上代码是CachingExecutor中的片段,可以很容易看出,在执行查询时,先检查了cache。如果二级缓存中没有想要的数据,则会从数据库查询,得到结果后放到缓存中,然后在将结果返回给用户。

  • 使用二级缓存的前提
    mybatis中的二级缓存不是一个简单是全局缓存,它支持非常细粒度的配置,精确到每一个具体的查询语句。使用二级缓存大致需要以下三部的配置
    1)在核心配置文件中配置<setting name="cacheEnable" value="true">,这是二级缓存的全局开关。
 <setting name="cacheEnabled" value="true"/>

2)在sqlMapper配置文件中配置<cache/>,该标签用于将二级缓存的控制权交到每个mapper手里,同时,利用该标签还可以配置诸如回收策略、刷新频率,缓存大小,缓存类型等。

<cache        eviction = "FIFO"         flushInterval = "60000"        size="512"       readOnly="true"       type="org.mybatis.caches.ehcache.EhcacheCache"/>

3)在<select/>标签中应用useCache属性userCache=true,来进一步说明这个查询需要用到二级缓存,

 <select id="secondLevelCache" resultType="Pet" useCache="true">          select <include refid="column"/> from pet where owner = 'zhangsan'     </select>
  • 一级缓存与二级缓存的使用顺序
    从上面的图中,其实我们就可以看出mybatis在应用缓存时具体策略,首先会先从二级缓存查询数据(这个那个CachingExecutor的第一道关卡),如果没找到,则把寻找数据的人员交给被CachingExecutor装饰的BaseExecutor,BaseExecutor首先会查询当前会话的一级缓存(当然多数情况下是徒劳,二级缓存中都没有,一级缓存中怎么可能有呢),若没有找到数据,最终与数据库建立连接,得到数据,放入一级缓存,放入二级缓存,最后返回给用户。
    综上所述:
    1)二级缓存
    2)一级缓存
    3)查询数据库

  • 二级缓存的回收策略

    LRU – 最近最少使用的:移除最长时间不被使用的对象
    FIFO – 先进先出:按对象进入缓存的顺序来移除它们
    SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象
    WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象

0 0
原创粉丝点击