Mybatis读取缓存次序:

  1. 先从二级缓存中获取数据,如果有直接获取,如果没有进行下一步;
  2. 从一级缓存中取数据,有直接获取,如果没有进行下一步;
  3. 到数据库中进行查询,并保存到一级缓存中;
  4. 当sqlSession关闭的时候,把一级缓存中的数据保存在二级缓存中。

二级缓存的使用:

myBatis的二级缓存默认是不开启的。我们需要在mybatis的核心配置文件中配置setting选项 和 在Mapper的配置文件中加入cache标签

启用二缓存分两步:

1、在mybatis-config.xml中配置全局的参数

<!-- 开启二缓存 -->

<setting name="cacheEnabled" value="true" />

2.到Mapper配置文件中书写Cache标签

<cache></cache>

3、实体bean对象要实现java.io.Serializable接口

public class Clazz implements Serializable {
private int id;
private String name;
private List<Student> stus;

没有实现java.io.Serializable接口的错误提示:

@Test
public void testSecondCache1() {
System.out.println("==================testSecondCache1()======================");
SqlSession session = sqlSessionFactory.openSession();
ClazzMapper clazzMapper = session.getMapper(ClazzMapper.class);
Clazz clazz1 = clazzMapper.queryClazzById(1);
System.out.println("clazz1 = " + clazz1);
session.close(); SqlSession session2 = sqlSessionFactory.openSession();
ClazzMapper clazzMapper2 = session2.getMapper(ClazzMapper.class);
Clazz clazz2 = clazzMapper2.queryClazzById(1);
System.out.println("clazz2 = " + clazz2);
session2.close();
}

开启缓存后运行结果:

==================testSecondCache1()======================
DEBUG [main] - Cache Hit Ratio [com.soyoungboy.onetomany.mapper.ClazzMapper]: 0.0
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 1791868405.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@6acdbdf5]
DEBUG [main] - ==> Preparing: select c.*,s.id stu_id,s.name stu_name from t_clazz c left join t_student s on c.id = s.clazz_id where c.id = ?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <== Total: 3
clazz1 = Clazz [id=1, name=javaEE20170228, stus=[Student [id=1, name=stu0228_张三, clazz=null], Student [id=2, name=stu0228_李四, clazz=null], Student [id=3, name=stu0228_王五, clazz=null]]]
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@6acdbdf5]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@6acdbdf5]
DEBUG [main] - Returned connection 1791868405 to pool.
DEBUG [main] - Cache Hit Ratio [com.soyoungboy.onetomany.mapper.ClazzMapper]: 0.5
clazz2 = Clazz [id=1, name=javaEE20170228, stus=[Student [id=1, name=stu0228_张三, clazz=null], Student [id=2, name=stu0228_李四, clazz=null], Student [id=3, name=stu0228_王五, clazz=null]]]

常用的属性

userCache

  userCache默认值是true,表示启用缓存。

  如果设置useCache为false就表示不启用二级缓存,不影响一级缓存。

<!-- // 根据 id 查询 key的信息 -->
<!-- public Key queryKeyById(int id); -->
<select id="queryClazzById" parameterType="int"
resultMap="queryClazzById_resultMap" useCache="false">
select c.*,s.id
stu_id,s.name stu_name from
t_clazz c left join t_student s
on
c.id =
s.clazz_id
where
c.id = #{id} </select>

运行结果:

结果:
==================testSecondCache1()======================
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 394714818.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1786dec2]
DEBUG [main] - ==> Preparing: select c.*,s.id stu_id,s.name stu_name from t_clazz c left join t_student s on c.id = s.clazz_id where c.id = ?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <== Total: 3
clazz1 = Clazz [id=1, name=javaEE20170228, stus=[Student [id=1, name=stu0228_张三, clazz=null], Student [id=2, name=stu0228_李四, clazz=null], Student [id=3, name=stu0228_王五, clazz=null]]]
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1786dec2]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1786dec2]
DEBUG [main] - Returned connection 394714818 to pool.
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Checked out connection 394714818 from pool.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1786dec2]
DEBUG [main] - ==> Preparing: select c.*,s.id stu_id,s.name stu_name from t_clazz c left join t_student s on c.id = s.clazz_id where c.id = ?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <== Total: 3
clazz2 = Clazz [id=1, name=javaEE20170228, stus=[Student [id=1, name=stu0228_张三, clazz=null], Student [id=2, name=stu0228_李四, clazz=null], Student [id=3, name=stu0228_王五, clazz=null]]]
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1786dec2]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1786dec2]
DEBUG [main] - Returned connection 394714818 to pool.

flushCache

flushCache属性默认值是true,在update标签,delete标签,insert标签中有。

表示当执行插入,修改,删除语句的时候,会清空缓存。

如果设置为false,很有肯能会产生脏数据。

xml文件配置:

<!-- // 根据 id 查询 key的信息 -->
<!-- public Key queryKeyById(int id); -->
<select id="queryClazzById" parameterType="int"
resultMap="queryClazzById_resultMap" useCache="true">
select c.*,s.id
stu_id,s.name stu_name from
t_clazz c left join t_student s
on
c.id =
s.clazz_id
where
c.id = #{id} </select> <update id="updateClazz" parameterType="com.soyoungboy.onetomany.bean.Clazz"
flushCache="false">
update t_clazz set name =
#{name} where id = #{id}
</update>

测试的java代码:

@Test
public void testSecondCacheUpdate() {
System.out.println("======================================================");
SqlSession session = sqlSessionFactory.openSession();
ClazzMapper userMapper = session.getMapper(ClazzMapper.class);
Clazz user = userMapper.queryClazzById(1);
System.out.println(user);
session.close(); SqlSession session2 = sqlSessionFactory.openSession();
ClazzMapper userMapper2 = session2.getMapper(ClazzMapper.class);
userMapper2.updateClazz(new Clazz(1, "更新了"));
session2.commit();
session2.close(); SqlSession session1 = sqlSessionFactory.openSession();
ClazzMapper userMapper1 = session1.getMapper(ClazzMapper.class);
user = userMapper1.queryClazzById(1);
System.out.println(user);
session1.close();
System.out.println("======================================================");
}

现在看看是否产生脏数据:

======================================================
DEBUG [main] - Cache Hit Ratio [com.soyoungboy.onetomany.mapper.ClazzMapper]: 0.0
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 1791868405.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@6acdbdf5]
DEBUG [main] - ==> Preparing: select c.*,s.id stu_id,s.name stu_name from t_clazz c left join t_student s on c.id = s.clazz_id where c.id = ?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <== Total: 3
Clazz [id=1, name=javaEE20170228, stus=[Student [id=1, name=stu0228_张三, clazz=null], Student [id=2, name=stu0228_李四, clazz=null], Student [id=3, name=stu0228_王五, clazz=null]]]
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@6acdbdf5]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@6acdbdf5]
DEBUG [main] - Returned connection 1791868405 to pool.
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Checked out connection 1791868405 from pool.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@6acdbdf5]
DEBUG [main] - ==> Preparing: update t_clazz set name = ? where id = ?
DEBUG [main] - ==> Parameters: 更新了(String), 1
(Integer)
DEBUG [main] - <== Updates: 1
DEBUG [main] - Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@6acdbdf5]
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@6acdbdf5]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@6acdbdf5]
DEBUG [main] - Returned connection 1791868405 to pool.
DEBUG [main] - Cache Hit Ratio [com.soyoungboy.onetomany.mapper.ClazzMapper]: 0.5
Clazz [id=1, name=javaEE20170228, stus=[Student [id=1, name=stu0228_张三, clazz=null], Student [id=2, name=stu0228_李四, clazz=null], Student [id=3, name=stu0228_王五, clazz=null]]]
如上所示,当usecache为true ,flushcache为false,不清空的时候就会出现脏数据

中间更新了数据为"更新了",但是接下来数据并没有读取更新后的数据,而是读取缓存中原有的数据,即脏数据。

<cache></cache>标签的介绍和说明undefined

默认的<cache/>标签的作用:

1、映射语句文件中的所有 select 语句将会被缓存。

2、射语句文件中的所有 insert,update 和 delete 语句会刷新缓存。

3、缓存会使用 Least Recently Used(LRU,最近最少使用的)算法来收回。

4、根据时间表(比如 no Flush Interval,没有刷新间隔), 缓存不会以任何时间顺序 来刷新。

5、缓存会存储列表集合或对象(无论查询方法返回什么)的 1024 个引用。

6、缓存会被视为是 read/write(可读/可写)的缓存,意味着对象检索不是共享的,而 且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。

cache标签示例解析:

<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>

eviction 属性表示缓存策略。

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

默认的是 LRU。

flushInterval 属性表示间隔多长时间刷新一下缓冲区,清理一下溢出的数据。以毫秒为单位。

size 属性表示缓存中可以保存多少个对象。默认是1024。

readOnly 属性表示是否只读。如果设置为true。表示缓存中只有一个对象。如果设置为false(默认)每次取出来都会反序列化拷贝一份。

type 属性表示自定义二级缓存对象。

 
 
 
 

mybatis 二级缓存的更多相关文章

  1. mybatis二级缓存应用及与ehcache整合

    mybaits的二级缓存是mapper范围级别,除了在SqlMapConfig.xml设置二级缓存的总开关,还要在具体的mapper.xml中开启二级缓存. 1.开启mybatis的二级缓存 在核心配 ...

  2. 深入了解MyBatis二级缓存

    深入了解MyBatis二级缓存 标签: mybatis二级缓存 2015-03-30 08:57 41446人阅读 评论(13) 收藏 举报  分类: Mybatis(51)  版权声明:版权归博主所 ...

  3. MyBatis二级缓存配置

    正如大多数持久层框架一样,MyBatis 同样提供了一级缓存和二级缓存的支持 Mybatis二级缓存是SessionFactory,如果两次查询基于同一个SessionFactory,那么就从二级缓存 ...

  4. mybatis二级缓存

    二级缓存区域是根据mapper的namespace划分的,相同namespace的mapper查询数据放在同一个区域,如果使用mapper代理方法每个mapper的namespace都不同,此时可以理 ...

  5. 如何细粒度地控制你的MyBatis二级缓存(mybatis-enhanced-cache插件实现)

    前几天网友chanfish 给我抛出了一个问题,笼统地讲就是如何能细粒度地控制MyBatis的二级缓存问题,酝酿了几天,觉得可以写个插件来实现这个这一功能.本文就是从问题入手,一步步分析现存的MyBa ...

  6. MyBatis 二级缓存全详解

    目录 MyBatis 二级缓存介绍 二级缓存开启条件 探究二级缓存 二级缓存失效的条件 第一次SqlSession 未提交 更新对二级缓存影响 探究多表操作对二级缓存的影响 二级缓存源码解析 二级缓存 ...

  7. Springboot整合Ehcache 解决Mybatis二级缓存数据脏读 -详细

    前面有写了一篇关于这个,但是这几天又改进了一点,就单独一篇在详细说明一下 配置 application.properties ,启用Ehcache # Ehcache缓存 spring.cache.t ...

  8. Spring Boot 入门(十):集成Redis哨兵模式,实现Mybatis二级缓存

    本片文章续<Spring Boot 入门(九):集成Quartz定时任务>.本文主要基于redis实现了mybatis二级缓存.较redis缓存,mybaits自带缓存存在缺点(自行谷歌) ...

  9. Mybatis 二级缓存应用 (21)

    [MyBatis 二级缓存] 概述:一级缓存作用域为同一个SqlSession对象,而二级缓存用来解决一级缓存不能夸会话共享,作用范围是namespace级,可以被多个SqlSession共享(只要是 ...

  10. 使用redis做mybaties的二级缓存(2)-Mybatis 二级缓存小心使用

    Mybatis默认对二级缓存是关闭的,一级缓存默认开启: 下面就说说为什么使用二级缓存需要注意: 二级缓存是建立在同一个namespace下的,如果对表的操作查询可能有多个namespace,那么得到 ...

随机推荐

  1. C#复习笔记(2)--C#1所搭建的核心基础

    通过对C#1所搭建的核心基础的深入了解,可以知道之后的C#版本在C#1的基础上做了很多扩展,而这些扩展都是基于C#搭建的核心基础而来的. 委托 一.编写委托的过程 委托经常和C语言的“函数指针”挂钩. ...

  2. 关于spring的源码的理解

    从最基础的Hello World开始. spring的Hello World就三行代码: public void test() { ApplicationContext context = new C ...

  3. [转帖]NUMA架构的CPU -- 你真的用好了么?

    NUMA架构的CPU -- 你真的用好了么? 本文从NUMA的介绍引出常见的NUMA使用中的陷阱,继而讨论对于NUMA系统的优化方法和一些值得关注的方向. 文章欢迎转载,但转载时请保留本段文字,并置于 ...

  4. [转帖]tar高级教程:增量备份、定时备份、网络备份

    tar高级教程:增量备份.定时备份.网络备份 作者: lesca 分类: Tutorials, Ubuntu 发布时间: 2012-03-01 11:42 ė浏览 27,065 次 61条评论 一.概 ...

  5. vue图片被加了盗链

    https://www.cnblogs.com/dongcanliang/archive/2017/04/01/6655061.html <meta name="referrer&qu ...

  6. solr单机版搭建

    需要把solr服务器安装到linux环境: 第一步:安装linux.jdk.tomcat. [root@bogon ~]# ll total 8044 -rw-r--r--. 1 root root ...

  7. JUC虚假唤醒(六)

    为什么条件锁会产生虚假唤醒现象(spurious wakeup)? ​ 在不同的语言,甚至不同的操作系统上,条件锁都会产生虚假唤醒现象.所有语言的条件锁库都推荐用户把wait()放进循环里: whil ...

  8. Atcoder Beginner Contest 121 D - XOR World(区间异或和)

    题目链接:https://atcoder.jp/contests/abc121/tasks/abc121_d 题目很裸(Atcoder好像都比较裸 就给一个区间求异或和 n到1e12 肯定不能O(n) ...

  9. hdu—3861(tarjan+二分图)

    题意:给你n个城市,每个城市之间有一条有向边,将城市划分为几个区域,问你最小的划分方法, 划分规则为:能相互到达的放在一个区域:然后区域内的a,b两点肯定存在某种方式,使得a能到b或者b能到a(注意, ...

  10. Tyche 2147 旅行

    题目描述 你有m元钱,将要游览n个国家.每一个国家有一种商品,其中第i个国家商品的单价为ai元.每到一个国家,你会用手上的钱疯狂购买这个国家的商品,直到剩余的钱无法购买为止. 现在你要决定游览这n个国 ...