Code皮皮虾 一个沙雕而又有趣的憨憨少年,和大多数小伙伴们一样喜欢听歌、游戏,当然除此之外还有写作的兴趣,emm...,日子还很长,让我们一起加油努力叭🌈
如果觉得写得不错的话,球球一个关注哦(☆▽☆)
什么是Mybatis一级缓存?
Mybatis中的一级缓存又叫查询缓存,顾名思义:只有查询才能缓存,更新、删除、插入等等不会会使用到。
这个一级缓存就是说:在执行一次SQL查询或者SQL更新之后,这条SQL语句并不会消失,而是被MyBatis 缓存起来,当再次执行相同SQL语句的时候,就会直接从缓存中进行提取,而不是再次执行SQL命令从数据库中查询。
案例演示
基于同一个SqlSession实验
如下是根据用户ID查询用户,我们分别查询三次
@Test
void getUserById() {
//获取SqlSession
SqlSession sqlSession = MybatisUtils.gerSqlSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
User user = userDao.getUserById(1);
System.out.println(user);
System.out.println("==================");
UserDao userDao1 = sqlSession.getMapper(UserDao.class);
User user1 = userDao1.getUserById(1);
System.out.println(user1);
System.out.println("==================");
UserDao userDao2 = sqlSession.getMapper(UserDao.class);
User user2 = userDao2.getUserById(1);
System.out.println(user2);
}
查看执行结果,可以看到只有执行第一次查询的时候才是从数据库中查询的,第二次、三次都是直接从缓存中拿去的数据
所以Mybatis日志只打印了一次
既然如此,那我们在第一次和第二次之间清空一下缓存,那么会打印出几条日志呢???
@Test
void getUserById() {
SqlSession sqlSession = MybatisUtils.gerSqlSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
User user = userDao.getUserById(1);
System.out.println(user);
System.out.println("==================");
//清空缓存
sqlSession.clearCache();
UserDao userDao1 = sqlSession.getMapper(UserDao.class);
User user1 = userDao1.getUserById(1);
System.out.println(user1);
System.out.println("==================");
UserDao userDao2 = sqlSession.getMapper(UserDao.class);
User user2 = userDao2.getUserById(1);
System.out.println(user2);
}
相信聪明的小伙伴已经想到了会打印出两条日志
当然,以上是基于同一个SqlSession的情况下来进行实验的,那么接下来我们基于不同SqlSession实验
基于不同SqlSession实验
@Test
void getUserById() {
SqlSession sqlSession1 = MybatisUtils.gerSqlSession();
UserDao userDao = sqlSession1.getMapper(UserDao.class);
User user = userDao.getUserById(1);
System.out.println(user);
System.out.println("==================");
SqlSession sqlSession2 = MybatisUtils.gerSqlSession();
UserDao userDao1 = sqlSession2.getMapper(UserDao.class);
User user1 = userDao1.getUserById(1);
System.out.println(user1);
System.out.println("==================");
SqlSession sqlSession3 = MybatisUtils.gerSqlSession();
UserDao userDao2 = sqlSession3.getMapper(UserDao.class);
User user2 = userDao2.getUserById(1);
System.out.println(user2);
}
可以看到,基于不同SqlSession的查询是独立的
小结论
一级缓存(查询缓存)是 SqlSession级别 的缓存。不同的 sqlSession 之间的缓存区域(HashMap)是互相不影响的。
源码探究
继续下一步
来到关键方法,可以看到下面是通过 switch 判断类型,我们是查询,所以可以直接来到 SELECT case中
可以看到SELECT 的case中有一行关键的代码,就是通过SqlSession调用的 selectOne方法,我们直接进去
selectOne中会调用当前类的 selectList
方法,我们继续进去
继续进去
来到关键的 query
方法 ,可以看到这里会去创建 缓存Key
第一次进来,cache为null,所以直接调用return的方法
关键!关键!关键!关键!关键!关键!关键!
本文同时参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金
Code皮皮虾 一个沙雕而又有趣的憨憨少年,和大多数小伙伴们一样喜欢听歌、游戏,当然除此之外还有写作的兴趣,emm...,日子还很长,让我们一起加油努力叭🌈
如果觉得写得不错的话,球球一个关注哦😉
回顾标题:Mybatis一级缓存是什么???
看了下面这张图相信大家都懂了,一级缓存(查询缓存)就是一个HashMap,而且每个SqlSession中有着各自独立的HashMap,跟ThreadLocal有点异曲同工之妙。
image-20211111104740717
最后总结
Mybatis一级缓存是SqlSession级别的缓存,对于SqlSession内部有着HashMap进行缓存,各个SqlSession之间互不干扰,通过构造唯一key,确保多次执行相同SQL时,可以在之后的执行中直接从缓存中获取,减小数据库访问压力。
构造唯一key
为什么一级缓存又叫查询缓存?
因为最后在BaseExecutor中进行执行的时候都没有像查询一样去缓存获取数据,也没有将数据缓存的操作
insert、delete、update在BaseExecutor中调用的都是update方法,所以都没有涉及到缓存。
最后
我是 Code皮皮虾,一个热爱分享知识的 皮皮虾爱好者,未来的日子里会不断更新出对大家有益的博文,期待大家的关注!!!
创作不易,如果这篇博文对各位有帮助,希望各位小伙伴可以一键三连哦!,感谢支持,我们下次再见~~~