mybatis缓存之一级缓存(二) - Kevin_zheng

zhenghengbin 2021-11-29 原文

这篇文章介绍下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调用的方法是有关系的

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


这个是根据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关闭后,缓存就不存在了

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时会清空缓存

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()也会清空缓存

这里是在第一次查询后,紧接着进行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不会清空缓存。这里的代码就证明了

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

发表于
2020-06-26 17:50 
Kevin_zheng 
阅读(515
评论(1
编辑 
收藏 
举报

 

版权声明:本文为zhenghengbin原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/zhenghengbin/p/13195727.html

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

  1. 【PS扩展面板】DR5高级版-西域摄影 – 开发小飞

    【PS扩展面板】DR5高级版-西域摄影 1、插件说明 DR5.0插件高级版是一款可以在PS中使用的美颜磨皮插件 […]...

  2. 词云图 – 挥辉

    词云图 Posted on 2018-09-11 06:55  挥辉  阅读(257)  评论(0)  编辑  […]...

  3. PHP – 操作MySQL数据库

    第16章 PHP操作MySQL   学习要点: 1.PHP连接到MySQL 2.增删改查 3.其他常用函数   […]...

  4. syslog详解及配置远程发送日志和远程日志分类 – 冯海猛

    syslog详解及配置远程发送日志和远程日志分类 1、日志协议syslog 1.1、syslog简介    完 […]...

  5. 深度学习(Deep Learning)算法简介及其成功应用 – Freedom000

    深度学习(Deep Learning)算法简介及其成功应用 深度学习是机器学习理论中的一个新的研究领域,其动机 […]...

  6. Linux – 查看文件信息的三个命令

    ls命令 – list directory contents 显示文件详细信息:ls -l < […]...

  7. ipv6一致性检测 – 代码笔记~

    ipv6一致性检测 【IPv6 Ready Logo】Core符合性測試   這篇要介紹如何建置IPv6符合性 […]...

  8. 电脑 windows 微信 image 文件夹 dat 文件 打开 解码 转码 查看 图片 – 萝卜L

    电脑 windows 微信 image 文件夹 dat 文件 打开 解码 转码 查看 图片 参见: 写了一个电 […]...

随机推荐

  1. hive 优化大全

    404...

  2. 浅谈几类背包题

    浅谈几类背包题 浅谈几类背包题 摘要 关键字 正文 一、 引言 二、 背包的基本变换 1. 完全背包 2. 多 […]...

  3. 通过物理模型生成Java代码

    通过物理模型生成Java代码 软件开发过程中,我们一般是先针对数据库建模,物理建模完成后,生成数据库表,编码阶 […]...

  4. 【Linux常见问题】Centos7的网络配置问题

    在配置Centos7网络的时候,可能出出现虚拟机、本地以及外网三者之间ping不通的问题,可以从以下的几个方面 […]...

  5. SQLServer 存储过程详解

    Transact-SQL中的存储过程,非常类似于Java语言中的方法,它可以重复调用。当存储过程执行一次后,可 […]...

  6. js 实现手风琴

    <!DOCTYPE html> <html lang=”en”> […]...

  7. 【DevOps】团队敏捷开发系列–开山篇

    随着软件发布迭代的频率越来越高,传统的「瀑布型」(开发—测试—发布)模式已经不能满足快速交付的需求。2009 […]...

  8. NC65在日常开发中常用的代码写法

    NC65在日常开发中常用的代码写法 标题 NC65开发相关代码 版本 1.0.1 作者 walton 说明 收 […]...

展开目录

目录导航