MyBatis的二级缓存是Application级别的缓存,它可以提高对数据库查询的效率,以提高应用的性能。本文将全面分析MyBatis的二级缓存的设计原理。

如上图所示,当开一个会话时,一个SqlSession对象会使用一个Executor对象来完成会话操作,MyBatis的二级缓存机制的关键就是对这个Executor对象做文章。如果用户配置了"cacheEnabled=true",那么MyBatis在为SqlSession对象创建Executor对象时,会对Executor对象加上一个装饰者:CachingExecutor,这时SqlSession使用CachingExecutor对象来完成操作请求。CachingExecutor对于查询请求,会先判断该查询请求在Application级别的二级缓存中是否有缓存结果,如果有查询结果,则直接返回缓存结果;如果缓存中没有,再交给真正的Executor对象来完成查询操作,之后CachingExecutor会将真正Executor返回的查询结果放置到缓存中,然后在返回给用户。

CachingExecutorExecutor的装饰者,以增强Executor的功能,使其具有缓存查询的功能,这里用到了设计模式中的装饰者模式,

CachingExecutorExecutor的接口的关系如下类图所示:

MyBatis并不是简单地对整个Application就只有一个Cache缓存对象,它将缓存划分的更细,即是Mapper级别的,即每一个Mapper都可以拥有一个Cache对象,具体如下:

a.为每一个Mapper分配一个Cache缓存对象(使用<cache>节点配置);

b.多个Mapper共用一个Cache缓存对象(使用<cache-ref>节点配置);

a.为每一个Mapper分配一个Cache缓存对象(使用<cache>节点配置)

MyBatisApplication级别的二级缓存细分到Mapper级别,即对于每一个Mapper.xml,如果在其中使用了<cache>
节点,则MyBatis会为这个Mapper创建一个Cache缓存对象,如下图所示:

注:  上述的每一个Cache对象,都会有一个自己所属的namespace命名空间,并且会将Mapper的 namespace作为它们的ID;

b.多个Mapper共用一个Cache缓存对象(使用<cache-ref>节点配置)

如果你想让多个Mapper公用一个Cache的话,你可以使用<cache-ref
namespace="">
节点,来指定你的这个Mapper使用到了哪一个MapperCache缓存。

MyBatis对二级缓存的支持粒度很细,它会指定某一条查询语句是否使用二级缓存。

虽然在Mapper中配置了<cache>,并且为此Mapper分配了Cache对象,这并不表示我们使用Mapper中定义的查询语句查到的结果都会放置到Cache对象之中,我们必须指定Mapper中的某条选择语句是否支持缓存,即如下所示,在<select>
节点中配置useCache="true"Mapper才会对此Select的查询支持缓存特性,否则,不会对此Select查询,不会经过Cache缓存。如下所示,Select语句配置了useCache="true",则表明这条Select语句的查询会使用二级缓存。

  <select id="selectByMinSalary" resultMap="BaseResultMap" parameterType="java.util.Map" useCache="true">

总之,要想使某条Select查询支持二级缓存,你需要保证:

1.  MyBatis支持二级缓存的总开关:全局配置变量参数   cacheEnabled=true

   2. 该select语句所在的Mapper,配置了<cache> 或<cached-ref>节点,并且有效

   3. 该select语句的参数 useCache=true

4. 一级缓存和二级缓存的使用顺序

请注意,如果你的MyBatis使用了二级缓存,并且你的Mapperselect语句也配置使用了二级缓存,那么在执行select查询的时候,MyBatis会先从二级缓存中取输入,其次才是一级缓存,即MyBatis查询数据的顺序是:

       二级缓存    ———> 一级缓存——> 数据库

5. 二级缓存实现的选择

MyBatis对二级缓存的设计非常灵活,它自己内部实现了一系列的Cache缓存实现类,并提供了各种缓存刷新策略如LRU,FIFO等等;另外,MyBatis还允许用户自定义Cache接口实现,用户是需要实现org.apache.ibatis.cache.Cache接口,然后将Cache实现类配置在<cache 
type="">
节点的type属性上即可;除此之外,MyBatis还支持跟第三方内存缓存库如Memecached的集成,总之,使用MyBatis的二级缓存有三个选择:

1.MyBatis自身提供的缓存实现;

        2. 用户自定义的Cache接口实现;

        3.跟第三方内存缓存库的集成;

6.  MyBatis自身提供的二级缓存的实现

MyBatis自身提供了丰富的,并且功能强大的二级缓存的实现,它拥有一系列的Cache接口装饰者,可以满足各种对缓存操作和更新的策略。

MyBatis定义了大量的Cache的装饰器来增强Cache缓存的功能,如下类图所示。

对于每个Cache而言,都有一个容量限制,MyBatis各供了各种策略来对Cache缓存的容量进行控制,以及对Cache中的数据进行刷新和置换。MyBatis主要提供了以下几个刷新和置换策略:

LRU:(Least Recently Used),最近最少使用算法,即如果缓存中容量已经满了,会将缓存中最近做少被使用的缓存记录清除掉,然后添加新的记录;

FIFO:(First in first out),先进先出算法,如果缓存中的容量已经满了,那么会将最先进入缓存中的数据清除掉;

Scheduled:指定时间间隔清空算法,该算法会以指定的某一个时间间隔将Cache缓存中的数据清空;

6. 写在后面(关于涉及到的设计模式)

在二级缓存的设计上,MyBatis大量地运用了装饰者模式,如CachingExecutor, 以及各种Cache接口的装饰器。关于装饰者模式,读者可以阅读相关资料,我的另外一篇博文   
Java 设计模式 装饰者模式供读者参考。

转自:http://blog.csdn.net/luanlouis/article/details/41408341

《深入理解mybatis原理》 MyBatis的二级缓存的设计原理的更多相关文章

  1. 《深入理解mybatis原理7》 MyBatis的二级缓存的设计原理

    <深入理解mybatis原理> MyBatis的二级缓存的设计原理 MyBatis的二级缓存是Application级别的缓存,它可以提高对数据库查询的效率,以提高应用的性能.本文将全面分 ...

  2. mybatis深入理解(六)-----MyBatis的二级缓存的设计原理

    MyBatis的二级缓存是Application级别的缓存,它可以提高对数据库查询的效率,以提高应用的性能.本文将全面分析MyBatis的二级缓存的设计原理. 1.MyBatis的缓存机制整体设计以及 ...

  3. mybatis 使用redis实现二级缓存(spring boot)

    mybatis 自定义redis做二级缓存 前言 如果关注功能实现,可以直接看功能实现部分 何时使用二级缓存 一个宗旨---不常变的稳定而常用的 一级是默认开启的sqlsession级别的. 只在单表 ...

  4. Mybatis整合Redis实现二级缓存

    Mybatis集成ehcache . 为什么需要缓存 拉高程序的性能 . 什么样的数据需要缓存 很少被修改或根本不改的数据 业务场景比如:耗时较高的统计分析sql.电话账单查询sql等 . ehcac ...

  5. mybatis由浅入深day02_7.3二级缓存

    7.3 二级缓存 7.3.1 原理 下图是多个sqlSession请求UserMapper的二级缓存图解. 首先开启mybatis的二级缓存. sqlSession1去查询用户id为1的用户信息,查询 ...

  6. myBatis源码解析-二级缓存的实现方式

    1. 前言 前面近一个月去写自己的mybatis框架了,对mybatis源码分析止步不前,此文继续前面的文章.开始分析mybatis一,二级缓存的实现.附上自己的项目github地址:https:// ...

  7. mybatis结合redis实战二级缓存(六)

    之前的文章中我们意见分析了一级缓存.二级缓存的相关源码和基本原理,今天我们来分享下了mybatis二级缓存和redis的结合,当然mybatis二级缓存也可以和ehcache.memcache.OSC ...

  8. Mybatis 为什么不要用二级缓存

    https://www.cnblogs.com/liouwei4083/p/6025929.html mybatis 二级缓存不推荐使用 一 mybatis的缓存使用. 大体就是首先根据你的sqlid ...

  9. mybatis结合redis实战二级缓存

    之前的文章中我们意见分析了一级缓存.二级缓存的相关源码和基本原理,今天我们来分享下了mybatis二级缓存和redis的结合,当然mybatis二级缓存也可以和ehcache.memcache.OSC ...

随机推荐

  1. PLAYGROUND 延时运行

    PLAYGROUND 延时运行 由 王巍 (@ONEVCAT) 发布于 2015/09/16 从 WWDC 14 的 Keynote 上 Chris 的演示就能看出 Playground 异常强大,但 ...

  2. json 将key值以字符串形式取出

    int GetJsonCString(const Json::Value& value, char* str, int n){ if (!value.empty() && va ...

  3. (34)zabbix Queue队列

    概述 queue(队列)显示监控项等待刷新的时间,可以看到每种agent类型刷新时间,通过queue可以更好的体现出监控的一个指标.正常情况下,是一片绿色. 如果出现过多红色,那么需要留意一下.我们也 ...

  4. MariaDB数据库(五)

    1. MariaDB主从架构 1.1 概述 主从架构用来预防数据丢失.主从多用于网站架构,因为主从的同步机制是异步的,数据的同步有一定延迟,也就是说有可能会造成数据的丢失,但是性能比较好,因此网站大多 ...

  5. 初识Pyhon之准备环境

    安装成功python的运行环境之后,你可能要迫不及待大展身手了 如果你有一定的语言基础,那么基础这一块儿就可以简单的看看就可以了,但是你是一个编程语言的初学者.不着急,慢慢往下看 打开pycharm创 ...

  6. 双线性差值(由于分析sift源码 )

    双线性插值 双线性插值,顾名思义就是两个方向的线性插值加起来.所以只要了解什么是线性插值,分别在x轴和y轴都做一遍,就是双线性插值了. 线性插值的概念也非常简单粗暴,就是两个点A,B,要在AB中间插入 ...

  7. Lex与Yacc学习(七)之环境配置另一种方式

    必备工具 flex-2.5.4a-1.exe   和  bison-2.4.1-setup.exe   以及 cygwin2.738 的安装文件,下载地址 http://download.csdn.n ...

  8. Android自动化测试Uiautomator--UiScrollable接口简介

    UiScrollable主要包括以下几个方面的方法: 1.快速滚动 2.获取列表子元素 3.获取与设置最大滚动次数常量值 4.滑动区域校准常量设置与获取 5.先前与向后滚动 6.滚动到某个对象 7.设 ...

  9. BZOJ 2508: 简单题

    题目大意: 加入直线,删除直线,求点到所有直线的距离的平方和. 题解: 把点到直线的距离公式写出来,然后展开.维护六个值,计算一个二元的多项式的最小值. 对x和y分别求导,导数都为零时取到极值.然后解 ...

  10. 【19】javascript有哪些方法定义对象

    创建Object的方式有4种. 方式一: 通过对象字面量表示法(又称为直接量.原始方式). var obj = {name:"moyu"}; 方式二: 通过new和构造函数Obje ...