05、MyBatis 缓存
1.MyBatis缓存
MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制.缓存可以极大的提升查询效率.
1).一级缓存
public Employee getEmpById(Integer id);
<select id="getEmpById" resultType="com.atguigu.mybatis.bean.Employee" databaseId="mysql" >
select * from tbl_employee where id = #{id}
</select>
@Test
public void testFirstLevelCache() throws IOException {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession openSession = sqlSessionFactory.openSession();
try { EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
Employee emp01 = mapper.getEmpById(10);
System.out.println(emp01); //
Employee emp02 = mapper.getEmpById(1-0);
System.out.println(emp02);
System.out.println(emp01==emp02); }finally {
openSession.close();
}
}
2).一级缓存失效情况
(1).sqlSession不同
(2).sqlSession相同,查询条件不同(当前一级缓存中还没有这个数据)
(3).sqlSession相同,两次查询之间执行了增删改操作(这次增删改可能对当前数据有影响)
(4).sqlSession相同,手动清除了一级缓存
public Employee getEmpById(Integer id);
<select id="getEmpById" resultType="com.atguigu.mybatis.bean.Employee" databaseId="mysql" >
select * from tbl_employee where id = #{id}
</select>
@Test
public void testFirstLevelCache() throws IOException {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession openSession = sqlSessionFactory.openSession();
try { EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
Employee emp01 = mapper.getEmpById(10);
System.out.println(emp01); //1、Sqlsession不同
// SqlSession openSession2 = sqlSessionFactory.openSession();
// EmployeeMapper mapper2 = openSession2.getMapper(EmployeeMapper.class);
// Employee emp02 = mapper2.getEmpById(10); //2、sqlSession相同,查询条件不同
// Employee emp02 = mapper.getEmpById(3);
// System.out.println(emp02);
// System.out.println(emp01==emp02); //3、sqlSession相同,两次查询之间执行了增删改操作
// mapper.addEmp(new Employee(null, "testCache", "cache@cache.com", "1"));
// System.out.println("数据添加成功");
// Employee emp02 = mapper.getEmpById(10);
// System.out.println(emp02);
// System.out.println(emp01==emp02); //4、sqlSession相同,手动清除了一级缓存
openSession.clearCache();
Employee emp02 = mapper.getEmpById(10);
System.out.println(emp02);
System.out.println(emp01==emp02); }finally {
openSession.close();
}
}
3).二级缓存
二级缓存(second level cache),全局作用域缓存.
二级缓存默认不开启,需要手动配置.
MyBatis提供二级缓存的接口以及实现,缓存实现要求POJO实现Serializable接口.
二级缓存在 SqlSession 关闭或提交之后才会生效.
(1).二级缓存使用
二级缓存使用:
①.开启全局二级缓存配置:<setting name="cacheEnabled" value="true"/>
②.去需要使用二级缓存的xml中配置使用二级缓存;添加<cache></cache>
③.POJO需要实现序列化接口
<setting name="cacheEnabled" value="true"/>
<mapper namespace="com.atguigu.mybatis.dao.EmployeeMapper">
<!-- cache:使用二级缓存的namespace -->
<!-- eviction:缓存的清除策略;LRU|FIFO|SOFT|WEAK -->
<!-- LRU – 最近最少使用的:移除最长时间不被使用的对象。 -->
<!-- FIFO – 先进先出:按对象进入缓存的顺序来移除它们。 -->
<!-- SOFT – 软引用:基于垃圾回收器状态和软引用规则移除对象。 -->
<!-- WEAK – 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。 -->
<!-- flushInterval(刷新间隔):缓存多长时间清空一次,默认不清空,可以设置一个毫秒值启用刷新间隔 -->
<!-- readOnly(只读):属性可以被设置为 true 或 false -->
<!-- true:只读;mybatis认为所有从缓存中获取数据的操作都是只读操作,不会修改数据; -->
<!-- 只读的缓存会给所有调用者返回缓存对象的相同实例。 因此这些对象不能被修改。 提供了可观的性能提升-->
<!-- false:非只读;mybatis觉得获取的数据可能会被修改; -->
<!-- 可读写的缓存会(通过序列化)返回缓存对象的拷贝。 速度上会慢一些,但是更安全,因此默认值是 false -->
<!-- size(引用数目):属性可以被设置为任意正整数,要注意欲缓存对象的大小和运行环境中可用的内存资源.默认值是 1024 -->
<!-- type:属性指定的类必须实现 org.apache.ibatis.cache.Cache 接口.且提供一个接受 String 参数作为 id 的构造器 -->
<!-- 指定自定义缓存的全类名,实现Cache接口即可 -->
<!-- <cache eviction="FIFO" flushInterval="60000" readOnly="false" size="1024"></cache> -->
<cache></cache>
</mapper>
@Test
public void testSecondLevelCache() throws IOException {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession openSession = sqlSessionFactory.openSession();
SqlSession openSession2 = sqlSessionFactory.openSession();
try {
//1、
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
EmployeeMapper mapper2 = openSession2.getMapper(EmployeeMapper.class); Employee emp01 = mapper.getEmpById(1);
System.out.println(emp01);
openSession.close(); //第二次查询是从二级缓存中拿到的数据,并没有发送新的sql
//mapper2.addEmp(new Employee(null, "aaa", "nnn", "0"));
Employee emp02 = mapper2.getEmpById(1);
System.out.println(emp02);
openSession2.close();
}finally { }
}
(2).二级缓存工作原理
二级缓存工作原理:
①.一个会话,查询一条数,这个数据就会被放在当前会话的一级缓存中;
②.如果会话关闭;一级缓存中的数据会被保存到二级缓存中;新的会话查询信息,就可以参照二级缓存中的内容;
③.不同namespace查出的数据会放在自己对应的缓存中(map):sqlSession===EmployeeMapper==>Employee|DepartmentMapper===>Department
④.二级缓存工作效果:查出的数据都会被默认先放在一级缓存中.只有会话提交或者关闭以后,一级缓存中的数据才会转移到二级缓存中;
(3).二级缓存属性设置
①.cacheEnabled="true|false": false关闭缓存(二级缓存关闭)(一级缓存一直可用的)
②.每个select标签都有useCache="true|false": false不使用缓存(一级缓存依然使用,二级缓存不使用)
③.*每个增删改标签的:flushCache="true|false":(一级二级都会清除)增删改执行完成后就会清楚缓存;
测试:flushCache="true":一级缓存会被清空;二级也会被清空;每次查询之后都会清空缓存,缓存是没有被使用的;
④.sqlSession.clearCache();只是清除当前session的一级缓存
⑤.localCacheScope:本地缓存作用域;一级缓存SESSION;当前会话的所有数据保存在会话缓存中;STATEMENT:可以禁用一级缓存;
/** * MyBatis系统中默认定义了两级缓存:一级缓存和二级缓存 * 一级缓存(本地缓存):sqlSession级别的缓存;一级缓存是一直开启的;SqlSession级别的一个Map * 与数据库同一次会话期间查询到的数据会放在本地缓存中; * 以后如果需要获取相同的数据,直接从缓存中拿,没必要再去查询数据库; * 一级缓存失效情况:没有使用到一级缓存的情况,效果就是两次查询都需要向数据库发出查询 * 1、sqlSession不同 * 2、sqlSession相同,查询条件不同(当前一级缓存中还没有这个数据) * 3、sqlSession相同,两次查询之间执行了增删改操作(这次增删改可能对当前数据有影响) * 4、sqlSession相同,手动清除了一级缓存 * * 二级缓存(全局缓存):基于namespace级别的缓存;一个namespace对应一个二级缓存; * 二级缓存工作原理: * 1、一个会话,查询一条数,这个数据就会被放在当前会话的一级缓存中; * 2、如果会话关闭;一级缓存中的数据会被保存到二级缓存中;新的会话查询信息,就可以参照二级缓存中的内容; * 3、不同namespace查出的数据会放在自己对应的缓存中(map):sqlSession===EmployeeMapper==>Employee|DepartmentMapper===>Department * 二级缓存工作效果:查出的数据都会被默认先放在一级缓存中.只有会话提交或者关闭以后,一级缓存中的数据才会转移到二级缓存中; * 二级缓存使用: * 1、开启全局二级缓存配置:<setting name="cacheEnabled" value="true"/> * 2、去需要使用二级缓存的xml中配置使用二级缓存;添加<cache></cache> * 3、POJO需要实现序列化接口 * * 缓存有关属性/设置: * 1、cacheEnabled="true|false": false关闭缓存(二级缓存关闭)(一级缓存一直可用的) * 2、每个select标签都有useCache="true|false": false不使用缓存(一级缓存依然使用,二级缓存不使用) * 3、*每个增删改标签的:flushCache="true|false":(一级二级都会清除)增删改执行完成后就会清楚缓存; * 测试:flushCache="true":一级缓存会被清空;二级也会被清空;每次查询之后都会清空缓存,缓存是没有被使用的; * 4、sqlSession.clearCache();只是清除当前session的一级缓存 * 5、localCacheScope:本地缓存作用域;一级缓存SESSION;当前会话的所有数据保存在会话缓存中;STATEMENT:可以禁用一级缓存; * @throws IOException */ |
2.第三方缓存整合
EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider.
MyBatis定义了Cache接口方便我们进行自定义扩展.
参考文档:https://mybatis.org/mybatis-3/zh/sqlmap-xml.html#cache
http://mybatis.org/ehcache-cache/index.html
05、MyBatis 缓存的更多相关文章
- mybatis缓存
mybatis缓存http://www.cnblogs.com/QQParadise/articles/5109633.htmlhttp://www.mamicode.com/info-detail- ...
- MyBatis缓存详解
MyBatis缓存分为一级缓存和二级缓存 http://www.cnblogs.com/zemliu/archive/2013/08/05/3239014.html mybatis 二级cache h ...
- Mybatis缓存处理机制
一.MyBatis缓存介绍 正如大多数持久层框架一样,MyBatis 同样提供了一级缓存和二级缓存的支持 一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Se ...
- MyBatis缓存禁用失败
问题:MyBatis缓存无法禁用,同一个session的select查询结果一样,但是数据库其实已改变. 尝试达到想要的目的: 1.msgmapper.xml里的select标签加上 <sele ...
- MyBatis入门学习教程-MyBatis缓存
一.MyBatis缓存介绍 正如大多数持久层框架一样,MyBatis 同样提供了 package me.gacl.test; 2 import me.gacl.domain.User; import ...
- MyBatis学习总结(七)——Mybatis缓存(转载)
孤傲苍狼 只为成功找方法,不为失败找借口! MyBatis学习总结(七)--Mybatis缓存 一.MyBatis缓存介绍 正如大多数持久层框架一样,MyBatis 同样提供了一级缓存和二级缓存的 ...
- MyBatis学习总结(七)——Mybatis缓存
一.MyBatis缓存介绍 正如大多数持久层框架一样,MyBatis 同样提供了一级缓存和二级缓存的支持 一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Se ...
- MyBatis学习总结(七)——Mybatis缓存
一.MyBatis缓存介绍 正如大多数持久层框架一样,MyBatis 同样提供了一级缓存和二级缓存的支持 一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Se ...
- MyBatis——Mybatis缓存
原文:http://www.cnblogs.com/xdp-gacl/p/4270403.html MyBatis学习总结(七)--Mybatis缓存 一.MyBatis缓存介绍 正如大多数持久层框架 ...
随机推荐
- css:选择器(标签、类、ID、通配符)
1.css概述 主要的使用场景就是美化网页,布局页面 (1)html的局限性 它只关注内容的语义,只能做一些简单的样式,并且非常的臃肿和繁琐 (2)css对网页美化的作用 css是层叠样式表的简称,它 ...
- mysql页面查询
<?php $link = mysql_connect('127.0.0.1', 'root', 'root'); if (!$link) { die('Could not connect: ' ...
- python基本操作-文件、目录及路径
目录 1 前言 2 文件夹操作 2.1 查询操作 2.2 创建操作 2.3 删除操作 2.4 修改操作 3 文件操作 3.1 查询操作 3.2 创建操作 3.3 修改操作 3.4 删除 4 路径操作 ...
- SpringCloud Eureka Client和Server侧配置及Eureka高可用配置
一.Eureka注册中心和客户端配置Demo. 1.Server端 a.使用Idea创建Spring项目,如下所示: b.相关配置 application.yaml配置文件如下: # eureka本身 ...
- 【HBase】与关系型数据库区别、行式/列式存储
[HBase]与关系型数据库区别 1.本质区别 mysql:关系型数据库,行式存储,ACID,SQL,只能存储结构化数据 事务的原子性(Atomicity):是指一个事务要么全部执行,要么不执行,也就 ...
- Java实现 LeetCode 738 单调递增的数字(暴力)
738. 单调递增的数字 给定一个非负整数 N,找出小于或等于 N 的最大的整数,同时这个整数需要满足其各个位数上的数字是单调递增. (当且仅当每个相邻位数上的数字 x 和 y 满足 x <= ...
- Java实现 蓝桥杯VIP 算法训练 一元三次方程
问题描述 有形如:ax3+bx2+cx+d=0 这样的一个一元三次方程.给出该方程中各项的系数(a,b,c,d 均为实数),并约定该方程存在三个不同实根(根的范围在-100至100之间),且根与根之差 ...
- Java实现 LeetCode 54 螺旋矩阵
54. 螺旋矩阵 给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素. 示例 1: 输入: [ [ 1, 2, 3 ], [ 4, 5, 6 ], ...
- java实现第三届蓝桥杯数量周期
数量周期 [结果填空](满分9分) 复杂现象背后的推动力,可能是极其简单的原理.科学的目标之一就是发现纷繁复杂的自然现象背后的简单法则.爱因斯坦的相对论是这方面的典范例证. 很早的时候,生物学家观察某 ...
- java实现第七届蓝桥杯路径之谜
路径之谜 题目描述 小明冒充X星球的骑士,进入了一个奇怪的城堡. 城堡里边什么都没有,只有方形石头铺成的地面. 假设城堡地面是 n x n 个方格.[如图1.png]所示. 按习俗,骑士要从西北角走到 ...