这篇文章介绍下mybatis的一级缓存的生命周期

一级缓存的产生

一级缓存的产生,并不是看mappper的xml文件的select方法,看下面的例子

mapper.xml

  1. <select id="getById" resultType="entity.TempEntity">
  2. select * from temp where id = #{id}
  3. </select>

test

  1. @Test
  2. public void testSelectAsUpdate() throws IOException {
  3. InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
  4. SqlSessionFactory build = new SqlSessionFactoryBuilder().build(inputStream);
  5. SqlSession sqlSession = build.openSession();
  6. sqlSession.update("dao.Temp03Dao.getById", 1);
  7. sqlSession.update("dao.Temp03Dao.getById", 1);
  8. }

执行结果

  1. 2020-06-26 17:33:27,899 DEBUG [dao.Temp03Dao.getById] - ==> Preparing: select * from temp where id = ?
  2. 2020-06-26 17:33:27,922 DEBUG [dao.Temp03Dao.getById] - ==> Parameters: 1(Integer)
  3. 2020-06-26 17:33:27,923 DEBUG [dao.Temp03Dao.getById] - ==> Preparing: select * from temp where id = ?
  4. 2020-06-26 17:33:27,923 DEBUG [dao.Temp03Dao.getById] - ==> Parameters: 1(Integer)

我们可以看到执行了2次查询。说明并没有产生缓存。说明和sqlsession调用的方法是有关系的

只有调用上图中的方法才会产生一级缓存

一级缓存的销毁

1.关闭session



这个是根据debug看到的一级缓存的最终结构。下面是整个依赖的类图

test

  1. @Test
  2. public void test() throws IOException, NoSuchFieldException, IllegalAccessException {
  3. InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
  4. SqlSessionFactory build = new SqlSessionFactoryBuilder().build(inputStream);
  5. SqlSession sqlSession = build.openSession();
  6. TempEntity tempEntity1 = sqlSession.selectOne("dao.Temp03Dao.getById", 1);
  7. logger.info(tempEntity1);
  8. Field executorField = sqlSession.getClass().getDeclaredField("executor");
  9. executorField.setAccessible(true);
  10. CachingExecutor cachingExecutor = (CachingExecutor) executorField.get(sqlSession);
  11. Field declaredField = cachingExecutor.getClass().getDeclaredField("delegate");
  12. declaredField.setAccessible(true);
  13. SimpleExecutor simpleExecutor = (SimpleExecutor) declaredField.get(cachingExecutor);
  14. Field localCacheField = simpleExecutor.getClass().getSuperclass().getDeclaredField("localCache");
  15. localCacheField.setAccessible(true);
  16. PerpetualCache perpetualCache = (PerpetualCache) localCacheField.get(simpleExecutor);
  17. Field cacheField = perpetualCache.getClass().getDeclaredField("cache");
  18. cacheField.setAccessible(true);
  19. Map<Object,Object> map= (Map<Object, Object>) cacheField.get(perpetualCache);
  20. logger.info("缓存关闭前");
  21. for (Map.Entry<Object,Object> objectObjectEntry:map.entrySet()){
  22. logger.info(objectObjectEntry.getKey() + "===" + objectObjectEntry.getValue());
  23. }
  24. sqlSession.close();
  25. logger.info("缓存关闭后");
  26. for (Map.Entry<Object,Object> objectObjectEntry:map.entrySet()){
  27. logger.info(objectObjectEntry.getKey() + "=" + objectObjectEntry.getValue());
  28. }
  29. }

运行结果

  1. 2020-06-26 17:38:52,777 DEBUG [dao.Temp03Dao.getById] - ==> Preparing: select * from temp where id = ?
  2. 2020-06-26 17:38:52,801 DEBUG [dao.Temp03Dao.getById] - ==> Parameters: 1(Integer)
  3. 2020-06-26 17:38:52,824 DEBUG [dao.Temp03Dao.getById] - <== Total: 1
  4. 2020-06-26 17:38:52,824 INFO [TempTest] - TempEntity{id=1, value1='11111', value2='aaaaa'}
  5. 2020-06-26 17:38:52,825 INFO [TempTest] - 缓存关闭前
  6. 2020-06-26 17:38:52,826 INFO [TempTest] - -1654591322:461730790:dao.Temp03Dao.getById:0:2147483647:select * from temp where id = ?:1:dev===[TempEntity{id=1, value1='11111', value2='aaaaa'}]
  7. 2020-06-26 17:38:52,827 INFO [TempTest] - 缓存关闭后

可以看到session关闭后,缓存就不存在了

2.Commit提交

test

  1. @Test
  2. public void testCommit() throws IOException {
  3. InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
  4. SqlSessionFactory build = new SqlSessionFactoryBuilder().build(inputStream);
  5. SqlSession sqlSession = build.openSession();
  6. TempEntity tempEntity1 = sqlSession.selectOne("dao.Temp03Dao.getById", 1);
  7. logger.info(tempEntity1);
  8. sqlSession.commit();
  9. TempEntity tempEntity2 = sqlSession.selectOne("dao.Temp03Dao.getById", 1);
  10. logger.info(tempEntity2);
  11. logger.info(tempEntity1 == tempEntity2);
  12. }

运行结果

  1. 2020-06-26 17:40:40,821 DEBUG [dao.Temp03Dao.getById] - ==> Preparing: select * from temp where id = ?
  2. 2020-06-26 17:40:40,846 DEBUG [dao.Temp03Dao.getById] - ==> Parameters: 1(Integer)
  3. 2020-06-26 17:40:40,862 DEBUG [dao.Temp03Dao.getById] - <== Total: 1
  4. 2020-06-26 17:40:40,862 INFO [TempTest] - TempEntity{id=1, value1='11111', value2='aaaaa'}
  5. 2020-06-26 17:40:40,863 DEBUG [dao.Temp03Dao.getById] - ==> Preparing: select * from temp where id = ?
  6. 2020-06-26 17:40:40,863 DEBUG [dao.Temp03Dao.getById] - ==> Parameters: 1(Integer)
  7. 2020-06-26 17:40:40,864 DEBUG [dao.Temp03Dao.getById] - <== Total: 1
  8. 2020-06-26 17:40:40,864 INFO [TempTest] - TempEntity{id=1, value1='11111', value2='aaaaa'}
  9. 2020-06-26 17:40:40,864 INFO [TempTest] - false

说明sqlSession.commit时会清空缓存

3.Rollback

test

  1. @Test
  2. public void testRollback() throws IOException {
  3. InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
  4. SqlSessionFactory build = new SqlSessionFactoryBuilder().build(inputStream);
  5. SqlSession sqlSession = build.openSession();
  6. TempEntity tempEntity1 = sqlSession.selectOne("dao.Temp03Dao.getById", 1);
  7. logger.info(tempEntity1);
  8. sqlSession.rollback();
  9. TempEntity tempEntity2 = sqlSession.selectOne("dao.Temp03Dao.getById", 1);
  10. logger.info(tempEntity2);
  11. logger.info(tempEntity1 == tempEntity2);
  12. }

执行结果

  1. 2020-06-26 17:42:23,793 DEBUG [dao.Temp03Dao.getById] - ==> Preparing: select * from temp where id = ?
  2. 2020-06-26 17:42:23,833 DEBUG [dao.Temp03Dao.getById] - ==> Parameters: 1(Integer)
  3. 2020-06-26 17:42:23,843 DEBUG [dao.Temp03Dao.getById] - <== Total: 1
  4. 2020-06-26 17:42:23,843 INFO [TempTest] - TempEntity{id=1, value1='11111', value2='aaaaa'}
  5. 2020-06-26 17:42:23,844 DEBUG [dao.Temp03Dao.getById] - ==> Preparing: select * from temp where id = ?
  6. 2020-06-26 17:42:23,844 DEBUG [dao.Temp03Dao.getById] - ==> Parameters: 1(Integer)
  7. 2020-06-26 17:42:23,845 DEBUG [dao.Temp03Dao.getById] - <== Total: 1
  8. 2020-06-26 17:42:23,845 INFO [TempTest] - TempEntity{id=1, value1='11111', value2='aaaaa'}
  9. 2020-06-26 17:42:23,845 INFO [TempTest] - false

sqlSession.rollback()也会清空缓存

4.update更新

这里是在第一次查询后,紧接着进行update操作。这里与表无关。就是操作其它表,也会清空缓存。

test

  1. @Test
  2. public void testForUpdate() throws IOException {
  3. InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
  4. SqlSessionFactory build = new SqlSessionFactoryBuilder().build(inputStream);
  5. SqlSession sqlSession = build.openSession();
  6. TempEntity tempEntity1 = sqlSession.selectOne("dao.Temp03Dao.getById", 1);
  7. logger.info(tempEntity1);
  8. sqlSession.update("dao.Temp03Dao.updateById", 1);
  9. TempEntity tempEntity2 = sqlSession.selectOne("dao.Temp03Dao.getById", 1);
  10. logger.info(tempEntity2);
  11. logger.info(tempEntity1 == tempEntity2);
  12. }

运行结果

  1. 2020-06-26 17:45:43,997 DEBUG [dao.Temp03Dao.getById] - ==> Preparing: select * from temp where id = ?
  2. 2020-06-26 17:45:44,034 DEBUG [dao.Temp03Dao.getById] - ==> Parameters: 1(Integer)
  3. 2020-06-26 17:45:44,048 DEBUG [dao.Temp03Dao.getById] - <== Total: 1
  4. 2020-06-26 17:45:44,049 INFO [TempTest] - TempEntity{id=1, value1='11111', value2='aaaaa'}
  5. 2020-06-26 17:45:44,049 DEBUG [dao.Temp03Dao.updateById] - ==> Preparing: update temp set value1 = 'ffffff' where id = ?
  6. 2020-06-26 17:45:44,049 DEBUG [dao.Temp03Dao.updateById] - ==> Parameters: 1(Integer)
  7. 2020-06-26 17:45:44,050 DEBUG [dao.Temp03Dao.updateById] - <== Updates: 1
  8. 2020-06-26 17:45:44,051 DEBUG [dao.Temp03Dao.getById] - ==> Preparing: select * from temp where id = ?
  9. 2020-06-26 17:45:44,051 DEBUG [dao.Temp03Dao.getById] - ==> Parameters: 1(Integer)
  10. 2020-06-26 17:45:44,052 DEBUG [dao.Temp03Dao.getById] - <== Total: 1
  11. 2020-06-26 17:45:44,053 INFO [TempTest] - TempEntity{id=1, value1='ffffff', value2='aaaaa'}
  12. 2020-06-26 17:45:44,053 INFO [TempTest] - false

这里还是在一个session会话中。记得之前有人给我说只要在一个session会话中,执行update不会清空缓存。这里的代码就证明了

5.clearCache 主动清除

test

  1. @Test
  2. public void testClearCatch() throws IOException {
  3. InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
  4. SqlSessionFactory build = new SqlSessionFactoryBuilder().build(inputStream);
  5. SqlSession sqlSession = build.openSession();
  6. TempEntity tempEntity1 = sqlSession.selectOne("dao.Temp03Dao.getById", 1);
  7. logger.info(tempEntity1);
  8. sqlSession.clearCache();
  9. TempEntity tempEntity2 = sqlSession.selectOne("dao.Temp03Dao.getById", 1);
  10. logger.info(tempEntity2);
  11. logger.info(tempEntity1 == tempEntity2);
  12. }

运行结果

  1. 2020-06-26 17:48:42,085 DEBUG [dao.Temp03Dao.getById] - ==> Preparing: select * from temp where id = ?
  2. 2020-06-26 17:48:42,110 DEBUG [dao.Temp03Dao.getById] - ==> Parameters: 1(Integer)
  3. 2020-06-26 17:48:42,124 DEBUG [dao.Temp03Dao.getById] - <== Total: 1
  4. 2020-06-26 17:48:42,124 INFO [TempTest] - TempEntity{id=1, value1='11111', value2='aaaaa'}
  5. 2020-06-26 17:48:42,125 DEBUG [dao.Temp03Dao.getById] - ==> Preparing: select * from temp where id = ?
  6. 2020-06-26 17:48:42,125 DEBUG [dao.Temp03Dao.getById] - ==> Parameters: 1(Integer)
  7. 2020-06-26 17:48:42,126 DEBUG [dao.Temp03Dao.getById] - <== Total: 1
  8. 2020-06-26 17:48:42,126 INFO [TempTest] - TempEntity{id=1, value1='11111', value2='aaaaa'}
  9. 2020-06-26 17:48:42,126 INFO [TempTest] - false

一级缓存 脏读问题

mybatis缓存之一级缓存(二)的更多相关文章

  1. 八 mybatis查询缓存(一级缓存,二级缓存)和ehcache整合

    1       查询缓存 1.1     什么是查询缓存 mybatis提供查询缓存,用于减轻数据压力,提高数据库性能. mybaits提供一级缓存,和二级缓存.

  2. Mybatis延迟加载, 一级缓存、二级缓存

    延迟加载 概念:MyBatis中的延迟加载,也称为懒加载,是指在进行关联查询时,按照设置延迟规则推迟对关联对象的select查询.延迟加载可以有效的减少数据库压力. (注意:MyBatis的延迟加载只 ...

  3. MyBatis加强(1)~缓存机制(一级缓存、二级缓存、第三方缓存技术redis、ehcache)

    一.缓存机制 使用缓存可以使应用更快地获取数据,避免频繁的数据库交互操作,尤其是在查询越多,缓存命中率越高 的情况下,缓存的作用就越明显. 1.缓存原理:Map ■ 查询时,先从缓存区查询:找到,返回 ...

  4. MyBatis 延迟加载,一级缓存,二级缓存设置

    什么是延迟加载 resultMap中的association和collection标签具有延迟加载的功能. 延迟加载的意思是说,在关联查询时,利用延迟加载,先加载主信息.使用关联信息时再去加载关联信息 ...

  5. mybatis由浅入深day02_7查询缓存_7.2一级缓存_一级缓存应用

    7 查询缓存 7.1 什么是查询缓存 mybatis提供查询缓存,用于减轻数据压力,提高数据库性能. mybaits提供一级缓存,和二级缓存. 一级缓存是SqlSession级别的缓存.在操作数据库时 ...

  6. 【MyBatis学习12】MyBatis中的一级缓存

    缓存的作用是减轻数据库的压力,提高数据库的性能的.mybatis中提供了一级缓存和二级缓存,先来看一下两个缓存的示意图:   从图中可以看出: 一级缓存是SqlSession级别的缓存.在操作数据库时 ...

  7. 阶段3 1.Mybatis_11.Mybatis的缓存_6 Mybatis中的一级缓存

    Mybatis中的一级缓存和二级缓存         一级缓存:             它指的是Mybatis中SqlSession对象的缓存.             当我们执行查询之后,查询的结 ...

  8. MyBatis之一级缓存及其一级缓存失效

    定义: 一级缓存:本地缓存:与数据库同一次会话(sqlSession)期间查询到的数据会放在本地缓存中,如果以后要获取相同的数据直接从缓存中获取,不会再次向数据库查询数据一个SqlSession拥有一 ...

  9. Mybatis进阶使用-一级缓存与二级缓存

    简介 缓存是一般的ORM 框架都会提供的功能,目的就是提升查询的效率和减少数据库的压力.跟Hibernate 一样,MyBatis 也有一级缓存和二级缓存,并且预留了集成第三方缓存的接口. 一级缓存 ...

  10. 【转】hibernate缓存:一级缓存和二级缓存

    什么是缓存? 缓存是介于物理数据源与应用程序之间,是对数据库中的数据复制一份临时放在内存中的容器,其作用是为了减少应用程序对物理数据源访问的次数,从而提高了应用程序的运行性能.Hibernate在进行 ...

随机推荐

  1. python初学者笔记(2):阿拉伯数字转换成中文大写

    题:输入一个数字,转换成中文大写的写法 可运行的程序(Python 2.7.9): # -*- coding: utf-8 -*- #在python2的py文件里面写中文,必须要添加一行声明文件编码的 ...

  2. Java实现 LeetCode 345 反转字符串中的元音字母

    345. 反转字符串中的元音字母 编写一个函数,以字符串作为输入,反转该字符串中的元音字母. 示例 1: 输入: "hello" 输出: "holle" 示例 ...

  3. Java实现迷宫城堡(强连通图的判定)

    1 问题描述 Problem Description 为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单 ...

  4. Java实现 蓝桥杯 历届试题 矩阵翻硬币

    问题描述 小明先把硬币摆成了一个 n 行 m 列的矩阵. 随后,小明对每一个硬币分别进行一次 Q 操作. 对第x行第y列的硬币进行 Q 操作的定义:将所有第 ix 行,第 jy 列的硬币进行翻转. 其 ...

  5. java实现猜生日

    ** 猜生日** 今年的植树节(2012年3月12日),小明和他的叔叔还有小伙伴们一起去植树.休息的时候,小明的同学问他叔叔多大年纪,他叔叔说:"我说个题目,看你们谁先猜出来!" ...

  6. java实现巧排扑克牌

    ** 巧排扑克牌** 小明刚上小学,学会了第一个扑克牌"魔术",到处给人表演.魔术的内容是这样的: 他手里握着一叠扑克牌:A,2,-J,Q,K 一共13张.他先自己精心设计它们的顺 ...

  7. Java实现第九届蓝桥杯第几天

    第几天 题目描述 2000年的1月1日,是那一年的第1天. 那么,2000年的5月4日,是那一年的第几天? 注意:需要提交的是一个整数,不要填写任何多余内容. import java.util.Cal ...

  8. 玩转计划任务命令:schtasks

    管理计划任务SCHTASKS /parameter [arguments] 描述:    允许管理员创建.删除.查询.更改.运行和中止本地或远程系统上的计划任务. 参数列表:    /Create   ...

  9. 01.vue-router的基本使用

    Vue前端路由 1. npm install vue-router --save 2.脚手架安装 一.目录结构 二.index.js // 0.导入vue和路由插件 import Vue from ' ...

  10. 07.Django-缓存

    目录 缓存 一.如何提高网站并发量? 二.缓存方式 1. 开发调式缓存 2. 内存缓存 3. 文件缓存 4. 数据库缓存 5. Memcache缓存 5.1 使用python-memcached模块 ...