Mybatis 中缓存分为一级缓存,二级缓存。

一、Mybatis 一级缓存

1.证明一级缓存的存在

一级缓存是 SqlSession 级别的缓存,只要 SqlSession 没有 flush 或 close,它就存在。

User findById(Integer userId);
<!-- 根据 id 查询 --><select id="findById" resultType="cn.oesoft.mybatis01.domain.User" parameterType="_int">select *from userwhere id = #{uid}</select>
@Testpublic void testFindById() {User user = userDao.findById(41);System.out.println("第一次查询的用户:"+user);User user2 = userDao.findById(41);System.out.println("第二次查询用户:"+user2);System.out.println(user == user2);}

我们可以发现,虽然在上面的代码中我们查询了两次,但最后只执行了一次数据库操作,这就是 Mybatis 提
供给我们的一级缓存在起作用了。因为一级缓存的存在,导致第二次查询 id 为 41 的记录时,并没有发出 sql 语句
从数据库中查询数据,而是从一级缓存中查询

2.一级缓存的分析

一级缓存是 SqlSession 范围的缓存,当调用 SqlSession 的修改,添加,删除,commit(),close()等方法时,就会清空一级缓存。

第一次发起查询用户 id 为 1 的用户信息,先去找缓存中是否有 id 为 1 的用户信息,如果没有,从数据库查
询用户信息。
得到用户信息,将用户信息存储到一级缓存中。
如果 sqlSession 去执行 commit 操作(执行插入、更新、删除),清空 SqlSession 中的一级缓存,这样
做的目的为了让缓存中存储的是最新的信息,避免脏读。
第二次发起查询用户 id 为 1 的用户信息,先去找缓存中是否有 id 为 1 的用户信息,缓存中有,直接从缓存
中获取用户信息。

3.测试一级缓存的清空

 /*** 测试一级缓存清空*/@Testpublic void testFirstLevelCache() {User user1 = userDao.findById(41);System.out.println(user1);session.close();//再次获取 SqlSession 对象session = factory.openSession();//session.clearCache();//此方法也可以清空缓存userDao = session.getMapper(IUserDao.class);User user2 = userDao.findById(41);System.out.println(user2);System.out.println(user1 == user2);}
当执行sqlSession.close()后,再次获取sqlSession并查询id=41的User对象时,又重新执行了sql
语句,从数据库进行了查询操作。
/*** 测试缓存的同步*/@Testpublic void testClearlCache() {//1.根据 id 查询用户User user1 = userDao.findById(41);System.out.println(user1);//2.更新用户信息user1.setUsername("update user clear cache");user1.setAddress("北京市海淀区");userDao.updateUser(user1);//3.再次查询 id 为 41 的用户User user2 = userDao.findById(41);System.out.println(user2);System.out.println(user1 == user2);}

二、Mybatis 二级缓存

二级缓存是 mapper 映射级别的缓存,多个 SqlSession 去操作同一个 Mapper 映射的 sql 语句,多个
SqlSession 可以共用二级缓存,二级缓存是跨 SqlSession 的。

1.二级缓存结构图

首先开启 mybatis 的二级缓存。
sqlSession1 去查询用户信息,查询到用户信息会将查询数据存储到二级缓存中。
如果 SqlSession3 去执行相同 mapper 映射下 sql,执行 commit 提交,将会清空该 mapper 映射下的二
级缓存区域的数据。
sqlSession2 去查询与 sqlSession1 相同的用户信息,首先会去缓存中找是否存在数据,如果存在直接从
缓存中取出数据。

2.二级缓存的开启与关闭

a.第一步:在 SqlMapConfig.xml 文件开启二级缓存

<!-- 开启二级缓存的支持 --><setting name="cacheEnabled" value="true"/>
因为 cacheEnabled 的取值默认就为 true,所以这一步可以省略不配置。为 true 代表开启二级缓存;为
false 代表不开启二级缓存。

b.第二步:配置相关的 Mapper 映射文件

<cache>标签表示当前这个 mapper 映射将使用二级缓存,区分的标准就看 mapper 的 namespace 值.

<mapper namespace="cn.oesoft.mybatis01.dao.IUserDao">
<!-- 开启二级缓存的支持 -->
<cache></cache>
</mapper>

c.第三步:配置 statement 上面的 useCache 属性

<!-- 根据 id 查询 -->
<select id="findById" resultType="user" parameterType="int" useCache="true">
select * from user where id = #{uid}
</select>
将 UserDao.xml 映射文件中的<select>标签中设置 useCache=”true”代表当前这个 statement 要使用
二级缓存,如果不使用二级缓存可以设置为 false。
注意:针对每次查询都需要最新的数据,要设置成 useCache=false,禁用二级缓存。

3.二级缓存测试

/*** 测试二级缓存*/@Testpublic void testSecondLevelCache(){SqlSession sqlSession1 = factory.openSession();IUserDao dao1 = sqlSession1.getMapper(IUserDao.class);User user1 = dao1.findById(41);System.out.println(user1);sqlSession1.close();//一级缓存消失SqlSession sqlSession2 = factory.openSession();IUserDao dao2 = sqlSession2.getMapper(IUserDao.class);User user2 = dao2.findById(41);System.out.println(user2);sqlSession2.close();System.out.println(user1 == user2);}

经过上面的测试,我们发现执行了两次查询,并且在执行第一次查询后,我们关闭了一级缓存,再去执行第二
次查询时,我们发现并没有对数据库发出 sql 语句,所以此时的数据就只能是来自于我们所说的二级缓存。

4.二级缓存注意事项

当我们在使用二级缓存时,所缓存的类一定要实现 java.io.Serializable 接口,这种就可以使用序列化
方式来保存对象。
所以上面的代码System.out.println(user1 == user2)的输出为false,见上图最后一行。

12-Mybatis 缓存相关推荐

  1. 实际测试例子+源码分析的方式解剖MyBatis缓存的概念

    前言: 前方高能! 本文内容有点多,通过实际测试例子+源码分析的方式解剖MyBatis缓存的概念,对这方面有兴趣的小伙伴请继续看下去~ 欢迎工作一到五年的Java工程师朋友们加入Java架构开发:79 ...

  2. MyBatis-学习笔记12【12.Mybatis注解开发】

    Java后端 学习路线 笔记汇总表[黑马程序员] MyBatis-学习笔记01[01.Mybatis课程介绍及环境搭建][day01] MyBatis-学习笔记02[02.Mybatis入门案例] M ...

  3. mybatis缓存二级缓存_MyBatis缓存与Apache Ignite的陷阱

    mybatis缓存二级缓存 一周前,MyBatis和Apache ignite 宣布支持apache ignite作为MyBatis缓存(L2缓存). 从技术上讲,MyBatis支持两个级别的缓存: ...

  4. MyBatis缓存与Apache Ignite的陷阱

    一周前,MyBatis和Apache ignite 宣布支持apache ignite作为MyBatis缓存(L2缓存). 从技术上讲,MyBatis支持两个级别的缓存: 本地缓存,默认情况下始终启用 ...

  5. 给我五分钟,带你彻底掌握 MyBatis 缓存的工作原理

    前言 在计算机的世界中,缓存无处不在,操作系统有操作系统的缓存,数据库也会有数据库的缓存,各种中间件如Redis也是用来充当缓存的作用,编程语言中又可以利用内存来作为缓存.自然的,作为一款优秀的ORM ...

  6. redis的基本操作And数据持久化方式以及redis实现mybatis缓存

    Redis 1.NoSql # NoSql(Not Only Sql),不仅仅是sql,泛指非关系型数据库 2.NoSql的诞生 随着互联网web2.0网站的兴起,传统的关系型数据库在高并发和特大规模 ...

  7. Mybatis 一级缓存,Mybatis 二级缓存,Mybatis 缓存失效

    Mybatis 一级缓存,Mybatis 二级缓存,Mybatis 缓存失效 ================================ ©Copyright 蕃薯耀 2021-06-24 ht ...

  8. mybats实操-前期入门写法分析,SqlSessionFactory 获取SqlSession, 系统核心配置文件 mybatis-config.xml,SQL映射XML文件,MyBatis缓存

    标题 偏向这一块的配置 打个预防针 尽量别用中文路径 尤其配置文件 1.导入数据库(smbms_db.sql) 下载maven并且配置环境变量 去IDEA配置好maven 以后maven项目直接用 m ...

  9. MyBatis复习笔记6:MyBatis缓存机制

    MyBatis缓存机制 MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制.缓存可以极大的提升查询效率. MyBatis系统中默认定义了两级缓存. 一级缓存和二级缓存. 默认情 ...

  10. Mybatis 缓存系统源码解析

    Mybatis 缓存系统源码解析 转载于:https://juejin.im/post/5bfa50905188251d0920006c

最新文章

  1. linux xampp eclipse xdebug 无法进入断点
  2. 没好域名?就得给自己换个名
  3. Java集合:HashMap线程不安全?有哪些表现?
  4. [系统集成] CI持续集成项目简介
  5. 提取Java集合的元素-Java 8方法
  6. 【Python CheckiO 题解】Striped Words
  7. mysql8.0 tar安装_CentOS7安装MySQL8.0 tar包
  8. 动态规划——乘积最大子数组(Leetcode 152)
  9. 洞仙歌·冰肌玉骨 [宋] 苏轼
  10. 部分网站为什么上不去_天机SEO:分析网站收录与排名的重要因素
  11. 让 Chrome 在后台运行
  12. ekho嵌入式Linux移植全过程
  13. NOI OJ 1.3 13:反向输出一个三位数 C语言
  14. 计算机打印机端口号,网络打印机端口号.doc
  15. 实现webIM技术小结——websocket IM原理篇
  16. HDUOJ---携程员工运动会场地问题
  17. R语言使用plot函数可视化数据散点图,使用title函数为可视化图像设置自定义标题名称、自定义adj参数将标题向右侧移动
  18. [USACO13NOV]挤奶牛Crowded Cows(洛谷 P3088)
  19. 软件测试之测试程序开发
  20. idea连接数据库快速生成pojo类

热门文章

  1. html按钮的下拉菜单,按钮下拉菜单
  2. 【Elasticsearch】 es watcher 视频 笔记
  3. 【高并发】JUC中等待多线程完成的工具类CountDownLatch
  4. 【ElasticSearch】ElasticSearch immense term错误
  5. 95-180-050-源码-Watermark-允许固定数量延迟的分配器(BoundedOutOfOrdernessTimestampExtractor)
  6. 95-235-070-源码-task-OneInputStreamTask
  7. java基础工具VisualVM介绍与详细使用
  8. 广东省计算机考试图片大小,广东省计算机等级考试(20190423051419).doc
  9. SpringBoot+拦截器+自定义异常+自定义注解+全局异常处理简单实现接口权限管理...
  10. 设计一个安全对外的API接口,需要考虑哪些方面?