MyBatis - 5.缓存机制
MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制。缓存可以极大的提升查询效率。
- MyBatis系统中默认定义了两级缓存。
- 一级缓存和二级缓存。
- 1、默认情况下,只有一级缓存(SqlSession级别的缓存,也称为本地缓存)开启。
- 2、二级缓存需要手动开启和配置,他是基于namespace级别的缓存。
- 3、为了提高扩展性。MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存
1.一级缓存
- 一级缓存(local cache), 即本地缓存, 作用域默认为sqlSession。当 Session flush 或 close 后, 该Session 中的所有 Cache 将被清空。
- 本地缓存不能被关闭, 但可以调用 clearCache() 来清空本地缓存, 或者改变缓存的作用域.
- 在mybatis3.1之后, 可以配置本地缓存的作用域.
在 mybatis.xml 中配置
| 设置参数 | 描述 | 有效值 | 默认值 |
|---|---|---|---|
| localCacheScope | MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。 默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会共享数据。 |
SESSION | STATEMENT |
1.1 一级缓存演示&失效情况
同一次会话期间只要查询过的数据都会保存在当
前SqlSession的一个Map中- key:hashCode+查询的SqlId+编写的sql查询语句+参数
一级缓存失效的四种情况
- 1、不同的SqlSession对应不同的一级缓存
- 2、同一个SqlSession但是查询条件不同
- 3、同一个SqlSession两次查询期间执行了任何一次增删改操作
- 4、同一个SqlSession两次查询期间手动清空了缓存
2.二级缓存
- 二级缓存(second level cache),全局作用域缓存
- 二级缓存默认不开启,需要手动配置
- MyBatis提供二级缓存的接口以及实现,缓存实现要求 POJO实现Serializable接口
- 二级缓存在 SqlSession 关闭或提交之后才会生效
(1)使用步骤
- 1、全局配置文件中开启二级缓存
<setting name="cacheEnabled" value="true"/>
- 2、需要使用二级缓存的映射文件处使用cache配置缓存
<cache />
- 3、注意:POJO需要实现Serializable接口
Mapper里面的
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
eviction 可用的回收策略有:
- LRU – 最近最少使用的:移除最长时间不被使用的对象。
- FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
- SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
- WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
flushInterval:刷新间隔,单位毫秒 •
- 默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新
size:引用数目,正整数
- 代表缓存最多可以存储多少个对象,太大容易导致内存溢出
readOnly:只读,true/false
- true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象 不能被修改。这提供了很重要的性能优势。
- false(默认):读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些, 但是安全,因此默认是 false。
(2)使用自定义缓存
除了这些自定义缓存的方式, 你也可以通过实现你自己的缓存或为其他第三方缓存方案 创建适配器来完全覆盖缓存行为。
<cache type="com.domain.something.MyCustomCache"/>
2.1 二级缓存案例:
参照上面的步骤:
(1)全局配置mybatis-config.xml
<settings>
<!--开启二级缓存-->
<setting name="cacheEnabled" value="true"></setting>
...
(2)在 employeeMapper.xml 里添加 <cache>标签
<mapper namespace="com.tangge.Mapper.employeeMapper">
<cache></cache>
(3)POJO需要实现 Serializable 接口
com.tangge.model.employee 实现接口 Serializable
@Alias("emp")
public class employee implements Serializable{
...
}
---->【测试】:
/**
* 缓存:
* - 一级缓存:本地缓存 sqlSession 级别
* 与数据库同一次会话期间查询到的数据会缓存到本地缓存中,以后需要获取相同数据,直接缓存中拿。
*
* - 二级缓存:全局缓存 nameSpace 级别
* 工作机制:
* 1.一条查询被放入一级缓存中。
* 2.如果会话关闭,一级缓存数据会被保存到二级缓存中。新查询,可以参照二级缓存。
* 3.sqlSession === EmployeeMapper ===> Employee
* DepartmentMapper===> Department
* 不同namespace查出的数据会被放在自己对应的缓存中(map)
* 效果:数据会从二级缓存中获取。
* 查出的数据,默认放在一级缓存中,只有会话提交关闭以后,一级缓存中数据才会放入二级缓存。
*/
public static void getTwoLevelCache() {
SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtil.getSqlSessionFactory();
SqlSession session = sqlSessionFactory.openSession();
SqlSession session2 = sqlSessionFactory.openSession();
try {
employeeMapper mapper = session.getMapper(employeeMapper.class);
employeeMapper mapper2 = session2.getMapper(employeeMapper.class);
//第1次查询
employee emp = mapper.getEmployeeById(1);
System.out.println(emp);
session.close();
//第2次查询
employee emp2 = mapper2.getEmployeeById(1);
System.out.println(emp2);
session2.close();
} finally {
}
}

注意个问题:
查出的数据,默认放在一级缓存中,只有会话提交关闭以后,一级缓存中数据才会放入二级缓存。

3.缓存有关设置
- 1、全局setting的cacheEnable:
- 配置二级缓存的开关。一级缓存一直是打开的。
- 2、select标签的useCache属性:
- 配置这个select是否使用二级缓存。一级缓存一直是使用的
- 3、sql标签的flushCache属性:
- 增删改默认flushCache=true。sql执行以后,会同时清空一级和二级缓存。
查询<select>标签:默认flushCache=false。
- 增删改默认flushCache=true。sql执行以后,会同时清空一级和二级缓存。
- 4、sqlSession.clearCache():
- 只是用来清除一级缓存。
- 5、当在某一个作用域 (一级缓存Session/二级缓存
Namespaces) 进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被clear。
4.第三方包

4.1 ehcache
http://www.java2s.com/example/jar/e/ehcache-core-index.html
ehcache-core-2.6.6.jar(降级测试)
slf4j.api-1.6.1.jar
slf4j-log4j12-1.7.1.jar
https://github.com/mybatis/ehcache-cache/releases
mybatis-ehcache-1.0.3
帮助文档:http://www.mybatis.org/ehcache-cache/
4.1.1 配置说明
diskStore : ehcache支持内存和磁盘两种存储
path :指定磁盘存储的位置
defaultCache : 默认的缓存
maxEntriesLocalHeap=”10000”
eternal=”false”
timeToIdleSeconds=”120”
timeToLiveSeconds=”120”
maxEntriesLocalDisk=”10000000”
diskExpiryThreadIntervalSeconds=”120”
memoryStoreEvictionPolicy=”LRU”
cache :自定的缓存,当自定的配置不满足实际情况时可以通过自定义(可以包含多个cache节点)
name : 缓存的名称,可以通过指定名称获取指定的某个Cache对象
maxElementsInMemory :内存中允许存储的最大的元素个数,0代表无限个
clearOnFlush:内存数量最大时是否清除。
eternal :设置缓存中对象是否为永久的,如果是,超时设置将被忽略,对象从不过期。根据存储数据的不同,例如一些静态不变的数据如省市区等可以设置为永不过时
timeToIdleSeconds : 设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
timeToLiveSeconds :缓存数据的生存时间(TTL),也就是一个元素从构建到消亡的最大时间间隔值,这只能在元素不是永久驻留时有效,如果该值是0就意味着元素可以停顿无穷长的时间。
overflowToDisk :内存不足时,是否启用磁盘缓存。
maxEntriesLocalDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。
maxElementsOnDisk:硬盘最大缓存个数。
diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
diskPersistent:是否在VM重启时存储硬盘的缓存数据。默认值是false。
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
4.1.2 配置步骤
1.配置文档:
<ehcache
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
updateCheck="false">
<diskStore path="E:\开发工具\jar安装包\缓存\ehcache-disksotre"/>
<defaultCache
maxElementsInMemory="20000"
maxElementsOnDisk="10000000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"
/>
<cache name="eternalCache"
maxElementsInMemory="20000"
eternal="true"
overflowToDisk="true"
diskPersistent="false"
timeToLiveSeconds="0"
diskExpiryThreadIntervalSeconds="120"
/>
</ehcache>
2.在Mapper的<cache>设置
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
4.1.3 修改一处Mapper,改其他所有
其他Mapper配置,引用同一个Mapper命名空间里的cache设置
<cache-ref namespace="">
好多坑
(1)ehcache-core-2.7.1.jar
问题:
1.Caused by: java.lang.ClassNotFoundException: org.terracotta.statistics.StatisticsManager
解决方案:
The previous 2.7.0 version had these classes present.
2.70 版本以上都有这个问题了
Our maven setup must is :
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.7.0</version>
<exclusions>
<exclusion>
<groupId>net.sf.ehcache.internal</groupId>
<artifactId>ehcache-terracotta-bootstrap</artifactId>
</exclusion>
<exclusion>
<groupId>org.terracotta.internal</groupId>
<artifactId>statistics</artifactId>
</exclusion>
</exclusions>
</dependency>
MyBatis - 5.缓存机制的更多相关文章
- mybatis的缓存机制及用例介绍
在实际的项目开发中,通常对数据库的查询性能要求很高,而mybatis提供了查询缓存来缓存数据,从而达到提高查询性能的要求. mybatis的查询缓存分为一级缓存和二级缓存,一级缓存是SqlSessio ...
- 深入浅出mybatis之缓存机制
目录 前言 准备工作 MyBatis默认缓存设置 缓存实现原理分析 参数localCacheScope控制的缓存策略 参数cacheEnabled控制的缓存策略 总结 前言 提到缓存,我们都会不约而同 ...
- MyBatis 的缓存机制
缓存机制可以减轻数据库的压力,原理是在第一查询时,将查询结果缓存起来,之后再查询同样的sql, 不是真的去查询数据库,而是直接返回缓存中的结果. 缓存可以降低数据库的压力,但同时可能无法得到最新的结果 ...
- MyBatis框架——缓存机制
使⽤缓存机制的作⽤也是减少 Java 应⽤程序与数据库的交互次数,从⽽提升程序的运⾏效率. ⽐如第 ⼀次查询出某个对象之后,MyBatis 会⾃动将其存⼊缓存,当下⼀次查询同⼀个对象时,就可以直接从 ...
- mybatis(四)缓存机制
转载:https://www.cnblogs.com/wuzhenzhao/p/11103043.html 缓存是一般的ORM 框架都会提供的功能,目的就是提升查询的效率和减少数据库的压力.跟Hibe ...
- mybatis的缓存机制(一级缓存二级缓存和刷新缓存)和mybatis整合ehcache
1.1 什么是查询缓存 mybatis提供查询缓存,用于减轻数据压力,提高数据库性能. mybaits提供一级缓存,和二级缓存. 一级缓存是SqlSession级别的缓存.在操作数据库时需要构造 s ...
- mybatis的缓存机制
一级缓存: MyBatis的一级缓存指的是在一个Session域内,session为关闭的时候执行的查询会根据SQL为key被缓存(跟mysql缓存一样,修改任何参数的值都会导致缓存失效) packa ...
- mybatis缓存机制
目录 mybatis缓存机制 Executor和缓存 一级缓存 小结 二级缓存 小结 mybatis缓存机制 mybatis支持一.二级缓存来提高查询效率,能够正确的使用缓存的前提是熟悉mybatis ...
- 聊聊MyBatis缓存机制【美团-推荐】
聊聊MyBatis缓存机制 2018年01月19日 作者: 凯伦 文章链接 18778字 38分钟阅读 前言 MyBatis是常见的Java数据库访问层框架.在日常工作中,开发人员多数情况下是使用My ...
随机推荐
- log4j - 使用教程说明
地址:http://www.codeceo.com/log4j-usage.html 日志是应用软件中不可缺少的部分,Apache的开源项目log4j是一个功能强大的日志组件,提供方便的日志记录.在a ...
- 【VMware vSphere】ESXi系统设置静态IP
写在前面: 为了方便管理,一般将ESXi系统的IP设置为静态 ESXi6.5系统和6.0系统类似,这里以ESXi6.0系统为例 1, 进入系 ...
- Wireshark技巧-过滤规则和显示规则【转】
转自:https://www.cnblogs.com/icez/p/3973873.html Wireshark是一个强大的网络协议分析软件,最重要的它是免费软件. 过滤规则 只抓取符合条件的包,在W ...
- 两种 AuthorizationSchemes 在 ASP.NET Core 2
Welcome to IdentityServer4: https://identityserver4.readthedocs.io/en/release/ 支持 ASP.NET Core 2 ...
- HTML5实现全屏
现在主流的浏览器都支持全屏,但是各家实现不一.下面是主流浏览器实现方法: // W3C 提议 element.requestFullscreen(); element.exitFullscreen() ...
- UPS不间断电源工作原理简述
原文地址:https://blog.csdn.net/uamix/article/details/52776297 一.定义 UPS即不间断电源,是将蓄电池(多为铅酸免维护蓄电池)与主机相连接,通过主 ...
- cache、session、cookie的区别
session把数据保存在服务器端,每一个用户都有属于自己的Session,与别人的不冲突就是说,你登陆系统后,你的信息(如账号.密码等)就会被保存在服务器上一个单独的session中,当你退出系统后 ...
- Linux系统下安装pycharm
在 linux下打开浏览器,搜索pycharm,点击download. 下载好的文件的名称可能是 ‘pycharm-professional-2018.3.5.tar.gz’. 打开终端界面,输入命令 ...
- 分页插件pagination.js
项目中有分页功能,之前都是自己写,样式不好看,功能也简单,就找了这个插件pagination.js 页面导入pagination.js html代码 <div class="list_ ...
- 机器学习之SVD分解
一.SVD奇异值分解的定义 假设是一个的矩阵,如果存在一个分解: 其中为的酉矩阵,为的半正定对角矩阵,为的共轭转置矩阵,且为的酉矩阵.这样的分解称为的奇异值分解,对角线上的元素称为奇异值,称为左奇异矩 ...