mybatis缓存之一级缓存(二)
这篇文章介绍下mybatis的一级缓存的生命周期
一级缓存的产生
一级缓存的产生,并不是看mappper的xml文件的select方法,看下面的例子
mapper.xml
<select id="getById" resultType="entity.TempEntity">
select * from temp where id = #{id}
</select>
test
@Test
public void testSelectAsUpdate() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = build.openSession();
sqlSession.update("dao.Temp03Dao.getById", 1);
sqlSession.update("dao.Temp03Dao.getById", 1);
}
执行结果
2020-06-26 17:33:27,899 DEBUG [dao.Temp03Dao.getById] - ==> Preparing: select * from temp where id = ?
2020-06-26 17:33:27,922 DEBUG [dao.Temp03Dao.getById] - ==> Parameters: 1(Integer)
2020-06-26 17:33:27,923 DEBUG [dao.Temp03Dao.getById] - ==> Preparing: select * from temp where id = ?
2020-06-26 17:33:27,923 DEBUG [dao.Temp03Dao.getById] - ==> Parameters: 1(Integer)
我们可以看到执行了2次查询。说明并没有产生缓存。说明和sqlsession调用的方法是有关系的

只有调用上图中的方法才会产生一级缓存
一级缓存的销毁
1.关闭session

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

test
@Test
public void test() throws IOException, NoSuchFieldException, IllegalAccessException {
InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = build.openSession();
TempEntity tempEntity1 = sqlSession.selectOne("dao.Temp03Dao.getById", 1);
logger.info(tempEntity1);
Field executorField = sqlSession.getClass().getDeclaredField("executor");
executorField.setAccessible(true);
CachingExecutor cachingExecutor = (CachingExecutor) executorField.get(sqlSession);
Field declaredField = cachingExecutor.getClass().getDeclaredField("delegate");
declaredField.setAccessible(true);
SimpleExecutor simpleExecutor = (SimpleExecutor) declaredField.get(cachingExecutor);
Field localCacheField = simpleExecutor.getClass().getSuperclass().getDeclaredField("localCache");
localCacheField.setAccessible(true);
PerpetualCache perpetualCache = (PerpetualCache) localCacheField.get(simpleExecutor);
Field cacheField = perpetualCache.getClass().getDeclaredField("cache");
cacheField.setAccessible(true);
Map<Object,Object> map= (Map<Object, Object>) cacheField.get(perpetualCache);
logger.info("缓存关闭前");
for (Map.Entry<Object,Object> objectObjectEntry:map.entrySet()){
logger.info(objectObjectEntry.getKey() + "===" + objectObjectEntry.getValue());
}
sqlSession.close();
logger.info("缓存关闭后");
for (Map.Entry<Object,Object> objectObjectEntry:map.entrySet()){
logger.info(objectObjectEntry.getKey() + "=" + objectObjectEntry.getValue());
}
}
运行结果
2020-06-26 17:38:52,777 DEBUG [dao.Temp03Dao.getById] - ==> Preparing: select * from temp where id = ?
2020-06-26 17:38:52,801 DEBUG [dao.Temp03Dao.getById] - ==> Parameters: 1(Integer)
2020-06-26 17:38:52,824 DEBUG [dao.Temp03Dao.getById] - <== Total: 1
2020-06-26 17:38:52,824 INFO [TempTest] - TempEntity{id=1, value1='11111', value2='aaaaa'}
2020-06-26 17:38:52,825 INFO [TempTest] - 缓存关闭前
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'}]
2020-06-26 17:38:52,827 INFO [TempTest] - 缓存关闭后
可以看到session关闭后,缓存就不存在了
2.Commit提交
test
@Test
public void testCommit() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = build.openSession();
TempEntity tempEntity1 = sqlSession.selectOne("dao.Temp03Dao.getById", 1);
logger.info(tempEntity1);
sqlSession.commit();
TempEntity tempEntity2 = sqlSession.selectOne("dao.Temp03Dao.getById", 1);
logger.info(tempEntity2);
logger.info(tempEntity1 == tempEntity2);
}
运行结果
2020-06-26 17:40:40,821 DEBUG [dao.Temp03Dao.getById] - ==> Preparing: select * from temp where id = ?
2020-06-26 17:40:40,846 DEBUG [dao.Temp03Dao.getById] - ==> Parameters: 1(Integer)
2020-06-26 17:40:40,862 DEBUG [dao.Temp03Dao.getById] - <== Total: 1
2020-06-26 17:40:40,862 INFO [TempTest] - TempEntity{id=1, value1='11111', value2='aaaaa'}
2020-06-26 17:40:40,863 DEBUG [dao.Temp03Dao.getById] - ==> Preparing: select * from temp where id = ?
2020-06-26 17:40:40,863 DEBUG [dao.Temp03Dao.getById] - ==> Parameters: 1(Integer)
2020-06-26 17:40:40,864 DEBUG [dao.Temp03Dao.getById] - <== Total: 1
2020-06-26 17:40:40,864 INFO [TempTest] - TempEntity{id=1, value1='11111', value2='aaaaa'}
2020-06-26 17:40:40,864 INFO [TempTest] - false
说明sqlSession.commit时会清空缓存
3.Rollback
test
@Test
public void testRollback() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = build.openSession();
TempEntity tempEntity1 = sqlSession.selectOne("dao.Temp03Dao.getById", 1);
logger.info(tempEntity1);
sqlSession.rollback();
TempEntity tempEntity2 = sqlSession.selectOne("dao.Temp03Dao.getById", 1);
logger.info(tempEntity2);
logger.info(tempEntity1 == tempEntity2);
}
执行结果
2020-06-26 17:42:23,793 DEBUG [dao.Temp03Dao.getById] - ==> Preparing: select * from temp where id = ?
2020-06-26 17:42:23,833 DEBUG [dao.Temp03Dao.getById] - ==> Parameters: 1(Integer)
2020-06-26 17:42:23,843 DEBUG [dao.Temp03Dao.getById] - <== Total: 1
2020-06-26 17:42:23,843 INFO [TempTest] - TempEntity{id=1, value1='11111', value2='aaaaa'}
2020-06-26 17:42:23,844 DEBUG [dao.Temp03Dao.getById] - ==> Preparing: select * from temp where id = ?
2020-06-26 17:42:23,844 DEBUG [dao.Temp03Dao.getById] - ==> Parameters: 1(Integer)
2020-06-26 17:42:23,845 DEBUG [dao.Temp03Dao.getById] - <== Total: 1
2020-06-26 17:42:23,845 INFO [TempTest] - TempEntity{id=1, value1='11111', value2='aaaaa'}
2020-06-26 17:42:23,845 INFO [TempTest] - false
sqlSession.rollback()也会清空缓存
4.update更新
这里是在第一次查询后,紧接着进行update操作。这里与表无关。就是操作其它表,也会清空缓存。
test
@Test
public void testForUpdate() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = build.openSession();
TempEntity tempEntity1 = sqlSession.selectOne("dao.Temp03Dao.getById", 1);
logger.info(tempEntity1);
sqlSession.update("dao.Temp03Dao.updateById", 1);
TempEntity tempEntity2 = sqlSession.selectOne("dao.Temp03Dao.getById", 1);
logger.info(tempEntity2);
logger.info(tempEntity1 == tempEntity2);
}
运行结果
2020-06-26 17:45:43,997 DEBUG [dao.Temp03Dao.getById] - ==> Preparing: select * from temp where id = ?
2020-06-26 17:45:44,034 DEBUG [dao.Temp03Dao.getById] - ==> Parameters: 1(Integer)
2020-06-26 17:45:44,048 DEBUG [dao.Temp03Dao.getById] - <== Total: 1
2020-06-26 17:45:44,049 INFO [TempTest] - TempEntity{id=1, value1='11111', value2='aaaaa'}
2020-06-26 17:45:44,049 DEBUG [dao.Temp03Dao.updateById] - ==> Preparing: update temp set value1 = 'ffffff' where id = ?
2020-06-26 17:45:44,049 DEBUG [dao.Temp03Dao.updateById] - ==> Parameters: 1(Integer)
2020-06-26 17:45:44,050 DEBUG [dao.Temp03Dao.updateById] - <== Updates: 1
2020-06-26 17:45:44,051 DEBUG [dao.Temp03Dao.getById] - ==> Preparing: select * from temp where id = ?
2020-06-26 17:45:44,051 DEBUG [dao.Temp03Dao.getById] - ==> Parameters: 1(Integer)
2020-06-26 17:45:44,052 DEBUG [dao.Temp03Dao.getById] - <== Total: 1
2020-06-26 17:45:44,053 INFO [TempTest] - TempEntity{id=1, value1='ffffff', value2='aaaaa'}
2020-06-26 17:45:44,053 INFO [TempTest] - false
这里还是在一个session会话中。记得之前有人给我说只要在一个session会话中,执行update不会清空缓存。这里的代码就证明了
5.clearCache 主动清除
test
@Test
public void testClearCatch() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = build.openSession();
TempEntity tempEntity1 = sqlSession.selectOne("dao.Temp03Dao.getById", 1);
logger.info(tempEntity1);
sqlSession.clearCache();
TempEntity tempEntity2 = sqlSession.selectOne("dao.Temp03Dao.getById", 1);
logger.info(tempEntity2);
logger.info(tempEntity1 == tempEntity2);
}
运行结果
2020-06-26 17:48:42,085 DEBUG [dao.Temp03Dao.getById] - ==> Preparing: select * from temp where id = ?
2020-06-26 17:48:42,110 DEBUG [dao.Temp03Dao.getById] - ==> Parameters: 1(Integer)
2020-06-26 17:48:42,124 DEBUG [dao.Temp03Dao.getById] - <== Total: 1
2020-06-26 17:48:42,124 INFO [TempTest] - TempEntity{id=1, value1='11111', value2='aaaaa'}
2020-06-26 17:48:42,125 DEBUG [dao.Temp03Dao.getById] - ==> Preparing: select * from temp where id = ?
2020-06-26 17:48:42,125 DEBUG [dao.Temp03Dao.getById] - ==> Parameters: 1(Integer)
2020-06-26 17:48:42,126 DEBUG [dao.Temp03Dao.getById] - <== Total: 1
2020-06-26 17:48:42,126 INFO [TempTest] - TempEntity{id=1, value1='11111', value2='aaaaa'}
2020-06-26 17:48:42,126 INFO [TempTest] - false
一级缓存 脏读问题

mybatis缓存之一级缓存(二)的更多相关文章
- 八 mybatis查询缓存(一级缓存,二级缓存)和ehcache整合
1 查询缓存 1.1 什么是查询缓存 mybatis提供查询缓存,用于减轻数据压力,提高数据库性能. mybaits提供一级缓存,和二级缓存.
- Mybatis延迟加载, 一级缓存、二级缓存
延迟加载 概念:MyBatis中的延迟加载,也称为懒加载,是指在进行关联查询时,按照设置延迟规则推迟对关联对象的select查询.延迟加载可以有效的减少数据库压力. (注意:MyBatis的延迟加载只 ...
- MyBatis加强(1)~缓存机制(一级缓存、二级缓存、第三方缓存技术redis、ehcache)
一.缓存机制 使用缓存可以使应用更快地获取数据,避免频繁的数据库交互操作,尤其是在查询越多,缓存命中率越高 的情况下,缓存的作用就越明显. 1.缓存原理:Map ■ 查询时,先从缓存区查询:找到,返回 ...
- MyBatis 延迟加载,一级缓存,二级缓存设置
什么是延迟加载 resultMap中的association和collection标签具有延迟加载的功能. 延迟加载的意思是说,在关联查询时,利用延迟加载,先加载主信息.使用关联信息时再去加载关联信息 ...
- mybatis由浅入深day02_7查询缓存_7.2一级缓存_一级缓存应用
7 查询缓存 7.1 什么是查询缓存 mybatis提供查询缓存,用于减轻数据压力,提高数据库性能. mybaits提供一级缓存,和二级缓存. 一级缓存是SqlSession级别的缓存.在操作数据库时 ...
- 【MyBatis学习12】MyBatis中的一级缓存
缓存的作用是减轻数据库的压力,提高数据库的性能的.mybatis中提供了一级缓存和二级缓存,先来看一下两个缓存的示意图: 从图中可以看出: 一级缓存是SqlSession级别的缓存.在操作数据库时 ...
- 阶段3 1.Mybatis_11.Mybatis的缓存_6 Mybatis中的一级缓存
Mybatis中的一级缓存和二级缓存 一级缓存: 它指的是Mybatis中SqlSession对象的缓存. 当我们执行查询之后,查询的结 ...
- MyBatis之一级缓存及其一级缓存失效
定义: 一级缓存:本地缓存:与数据库同一次会话(sqlSession)期间查询到的数据会放在本地缓存中,如果以后要获取相同的数据直接从缓存中获取,不会再次向数据库查询数据一个SqlSession拥有一 ...
- Mybatis进阶使用-一级缓存与二级缓存
简介 缓存是一般的ORM 框架都会提供的功能,目的就是提升查询的效率和减少数据库的压力.跟Hibernate 一样,MyBatis 也有一级缓存和二级缓存,并且预留了集成第三方缓存的接口. 一级缓存 ...
- 【转】hibernate缓存:一级缓存和二级缓存
什么是缓存? 缓存是介于物理数据源与应用程序之间,是对数据库中的数据复制一份临时放在内存中的容器,其作用是为了减少应用程序对物理数据源访问的次数,从而提高了应用程序的运行性能.Hibernate在进行 ...
随机推荐
- 最短路径——Dijkstar算法
背景:本文是在小甲鱼数据结构教学视频中的代码的基础上,添加详细注释而完成的.该段代码并不完整,仅摘录了核心算法部分,结合自己的思考,谈谈理解. Dijkstar算法理解: Dijkstar算法的核心思 ...
- Alpha总结展望——前事不忘后事之师
这个作业属于哪个课程 软件工程 这个作业要求在哪里 Alpha总结展望--前事不忘后事之师 这个作业的目标 Alpha总结展望 作业正文 正文 其他参考文献 无 一.个人感想总结 吴秋悦: 对Alph ...
- 【Mybatis】mybatis3入门
mybatis简介 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可 ...
- 看不见远程新建git分支
再网页上新建了一个git分支.然后在本地跑git branch -r(查看远程分支)/ git branch -a(查看所有分支)两个命令,都没有看到新建的那个分支.这是为啥呢??? 原因是因为:gi ...
- Java实现 LeetCode 508 出现次数最多的子树元素和
508. 出现次数最多的子树元素和 给出二叉树的根,找出出现次数最多的子树元素和.一个结点的子树元素和定义为以该结点为根的二叉树上所有结点的元素之和(包括结点本身).然后求出出现次数最多的子树元素和. ...
- Java实现 蓝桥杯VIP 基础练习 完美的代价
package 蓝桥杯VIP; import java.util.Scanner; public class 完美的代价 { public static int sum = 0; public sta ...
- Java实现 LeetCode 327 区间和的个数
327. 区间和的个数 给定一个整数数组 nums,返回区间和在 [lower, upper] 之间的个数,包含 lower 和 upper. 区间和 S(i, j) 表示在 nums 中,位置从 i ...
- java实现漏掉的账目明细
某财务部门结账时发现总金额不对头.很可能是从明细上漏掉了某1笔或几笔.如果已知明细账目清单,能通过编程找到漏掉的是哪1笔或几笔吗? 如果有多种可能,则输出所有可能的情况. 我们规定:用户输入的第一行是 ...
- System.PlatformNotSupportedException:“Operation is not supported on this platform.”
vs2019创建.net core3.1 的控制台应用程序 执行以下代码: using System; using System.Diagnostics; using System.Threading ...
- JAVA第三次blog总结
JAVA第三次blog总结 0.前言 这是我们在博客园上第三次写博客,也是本学期最后一次的JAVA学习大总结.现在我们的JAVA已经接近尾声了,对于编程思想和方法的改变依旧是难点,但是经过这一段时间的 ...