[+]html
MyBatis的二级缓存是Application级别的缓存,它能够提升对数据库查询的效率,以提升应用的性能。本文将全面分析MyBatis的二级缓存的设计原理。java
如上图所示,当开一个会话时,一个SqlSession对象会使用一个Executor对象来完成会话操做,MyBatis的二级缓存机制的关键就是对这个Executor对象作文章。若是用户配置了"cacheEnabled=true",那么MyBatis在为SqlSession对象建立Executor对象时,会对Executor对象加上一个装饰者:CachingExecutor,这时SqlSession使用CachingExecutor对象来完成操做请求。CachingExecutor对于查询请求,会先判断该查询请求在Application级别的二级缓存中是否有缓存结果,若是有查询结果,则直接返回缓存结果;若是缓存中没有,再交给真正的Executor对象来完成查询操做,以后CachingExecutor会将真正Executor返回的查询结果放置到缓存中,而后在返回给用户。算法
CachingExecutor是Executor的装饰者,以加强Executor的功能,使其具备缓存查询的功能,这里用到了设计模式中的装饰者模式,数据库
CachingExecutor和Executor的接口的关系以下类图所示:apache
MyBatis并非简单地对整个Application就只有一个Cache缓存对象,它将缓存划分的更细,便是Mapper级别的,即每个Mapper均可以拥有一个Cache对象,具体以下:设计模式
a.为每个Mapper分配一个Cache缓存对象(使用<cache>节点配置);缓存
b.多个Mapper共用一个Cache缓存对象(使用<cache-ref>节点配置);mybatis
a.为每个Mapper分配一个Cache缓存对象(使用<cache>节点配置)MyBatis将Application级别的二级缓存细分到Mapper级别,即对于每个Mapper.xml,若是在其中使用了<cache> 节点,则MyBatis会为这个Mapper建立一个Cache缓存对象,以下图所示:app
注: 上述的每个Cache对象,都会有一个本身所属的namespace命名空间,而且会将Mapper的 namespace做为它们的ID;性能
b.多个Mapper共用一个Cache缓存对象(使用<cache-ref>节点配置)若是你想让多个Mapper公用一个Cache的话,你可使用<cache-ref namespace="">节点,来指定你的这个Mapper使用到了哪个Mapper的Cache缓存。
MyBatis对二级缓存的支持粒度很细,它会指定某一条查询语句是否使用二级缓存。
虽然在Mapper中配置了<cache>,而且为此Mapper分配了Cache对象,这并不表示咱们使用Mapper中定义的查询语句查到的结果都会放置到Cache对象之中,咱们必须指定Mapper中的某条选择语句是否支持缓存,即以下所示,在<select> 节点中配置useCache="true",Mapper才会对此Select的查询支持缓存特性,不然,不会对此Select查询,不会通过Cache缓存。以下所示,Select语句配置了useCache="true",则代表这条Select语句的查询会使用二级缓存。
[html] view plain copy
总之,要想使某条Select查询支持二级缓存,你须要保证:
1. MyBatis支持二级缓存的总开关:全局配置变量参数 cacheEnabled=true
2. 该select语句所在的Mapper,配置了<cache> 或<cached-ref>节点,而且有效
3. 该select语句的参数 useCache=true
请注意,若是你的MyBatis使用了二级缓存,而且你的Mapper和select语句也配置使用了二级缓存,那么在执行select查询的时候,MyBatis会先从二级缓存中取输入,其次才是一级缓存,即MyBatis查询数据的顺序是:
二级缓存 ———> 一级缓存——> 数据库
MyBatis对二级缓存的设计很是灵活,它本身内部实现了一系列的Cache缓存实现类,并提供了各类缓存刷新策略如LRU,FIFO等等;另外,MyBatis还容许用户自定义Cache接口实现,用户是须要实现org.apache.ibatis.cache.Cache接口,而后将Cache实现类配置在<cache type="">节点的type属性上便可;除此以外,MyBatis还支持跟第三方内存缓存库如Memecached的集成,总之,使用MyBatis的二级缓存有三个选择:
1.MyBatis自身提供的缓存实现;
2. 用户自定义的Cache接口实现;
3.跟第三方内存缓存库的集成;
MyBatis自身提供了丰富的,而且功能强大的二级缓存的实现,它拥有一系列的Cache接口装饰者,能够知足各类对缓存操做和更新的策略。
MyBatis定义了大量的Cache的装饰器来加强Cache缓存的功能,以下类图所示。
对于每一个Cache而言,都有一个容量限制,MyBatis各供了各类策略来对Cache缓存的容量进行控制,以及对Cache中的数据进行刷新和置换。MyBatis主要提供了如下几个刷新和置换策略:
LRU:(Least Recently Used),最近最少使用算法,即若是缓存中容量已经满了,会将缓存中最近作少被使用的缓存记录清除掉,而后添加新的记录;
FIFO:(First in first out),先进先出算法,若是缓存中的容量已经满了,那么会将最早进入缓存中的数据清除掉;
Scheduled:指定时间间隔清空算法,该算法会以指定的某一个时间间隔将Cache缓存中的数据清空;
在二级缓存的设计上,MyBatis大量地运用了装饰者模式,如CachingExecutor, 以及各类Cache接口的装饰器。关于装饰者模式,读者能够阅读相关资料,个人另一篇博文 Java 设计模式 装饰者模式 供读者参考。
本文只是讲述MyBatis二级缓存的基本原理,关于自定义二级缓存和与第三方内存库的集成,将在后续的文章中再作讨论,敬请关注!
做者的话
本文是《深刻理解mybatis原理》系列的其中一篇,若是您有兴趣,请关注该系列的其余文章~
以为本文不错,顺手点个赞哦~~您的鼓励,是我继续分享知识的强大动力!
若是您以为有不妥或者错误的地方,还请您不吝指教!
-----------------------------------------------------------------------------------------------------------------------------------------
本文源自 http://blog.csdn.net/luanlouis/,如需转载,请注明出处,谢谢!