Mybatis 的一级缓存和二级缓存执行顺序
缓存-官方文档
文档地址: https://mybatis.org/mybatis-3/zh/sqlmap-xml.html#cache
Mybatis 的一级缓存和二级缓存执行顺序
缓存执行顺序是:二级缓存–>一级缓存–>数据库
说的再多不如眼见为实,让我们用代码来证明吧
测试
代码实现
- 修改com\nlc\mapper\MonsterMapperTest.java
演示二级缓存->一级缓存->DB执行的顺序
@Test public void cacheSeqTest() { System.out.println("查询第1次"); //DB, 会发出SQL, 分析cache hit ratio 0.0 Monster monster1 = monsterMapper.getMonsterById(3); System.out.println(monster1); //这里关闭sqlSession, 一级缓存数据没有 //当我们关闭一级缓存的时候,如果你配置二级缓存,那么一级缓存的数据,会放入到二级缓存 sqlSession.close(); sqlSession = MyBatisUtils.getSqlSession(); monsterMapper = sqlSession.getMapper(MonsterMapper.class); System.out.println("查询第2次"); //从二级缓存获取id=3 monster , 就不会发出SQL, 分析cache hit ratio 0.5 Monster monster2 = monsterMapper.getMonsterById(3); System.out.println(monster2); System.out.println("查询第3次"); //从二级缓存获取id=3 monster, 不会发出SQL, 分析cache hit ratio 0.6666 Monster monster3 = monsterMapper.getMonsterById(3); System.out.println(monster3); if (sqlSession != null) { sqlSession.close(); } System.out.println("操作成功"); }
运行结果
查询第1次 Cache Hit Ratio [com.nlc.mapper.MonsterMapper]: 0.0 Opening JDBC Connection Created connection 527829831. Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1f760b47] ==> Preparing: SELECT * FROM `monster` WHERE id = ? ==> Parameters: 3(Integer) <== Columns: id, age, birthday, email, gender, name, salary <== Row: 3, 51, 4015-09-12, qwrw@df.com, 1, 风衣精, 1965 <== Total: 1 Monster{id=3, age=51, name='风衣精', email='qwrw@df.com', birthday=Sat Sep 12 00:00:00 CST 4015, salary=1965.0, gender=1} Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1f760b47] Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1f760b47] Returned connection 527829831 to pool. 查询第2次 Cache Hit Ratio [com.nlc.mapper.MonsterMapper]: 0.5 Monster{id=3, age=51, name='风衣精', email='qwrw@df.com', birthday=Sat Sep 12 00:00:00 CST 4015, salary=1965.0, gender=1} 查询第3次 Cache Hit Ratio [com.nlc.mapper.MonsterMapper]: 0.6666666666666666 Monster{id=3, age=51, name='风衣精', email='qwrw@df.com', birthday=Sat Sep 12 00:00:00 CST 4015, salary=1965.0, gender=1} 操作成功
细节说明
- 不会出现一级缓存和二级缓存中有同一个数据。因为二级缓存(数据)是在一级缓存关闭之后才有的。
- 看这段代码, 修改com\nlc\mapper\MonsterMapperTest.java , 不关闭一级缓存, 看看运行效果
//分析缓存执行顺序 //二级缓存->一级缓存->DB //因为二级缓存(数据)是在一级缓存关闭之后才有的 @Test public void cacheSeqTest2() { System.out.println("查询第1次"); //DB , 会发出 SQL, cache hit ratio 0.0 Monster monster1 = monsterMapper.getMonsterById(3); System.out.println(monster1); //这里我们没有关闭sqlSession System.out.println("查询第2次"); //从一级缓存获取id=3 , cache hit ratio 0.0, 不会发出SQL Monster monster2 = monsterMapper.getMonsterById(3); System.out.println(monster2); System.out.println("查询第3次"); //还是从一级缓存获取id=3, cache hit ratio 0.0, 不会发出SQL Monster monster3 = monsterMapper.getMonsterById(3); System.out.println(monster3); if (sqlSession != null) { sqlSession.commit(); sqlSession.close(); } System.out.println("操作成功"); }
- 运行效果, 可以看到,在一级缓存存在的情况下,依然是先查询二级缓存,但是因为二级缓存,没有数据, 所以命中率都是0.0 , 可以debug 下。
查询第1次 Cache Hit Ratio [com.nlc.mapper.MonsterMapper]: 0.0 Opening JDBC Connection Created connection 485845532. Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1cf56a1c] ==> Preparing: SELECT * FROM `monster` WHERE id = ? ==> Parameters: 3(Integer) <== Columns: id, age, birthday, email, gender, name, salary <== Row: 3, 51, 4015-09-12, qwrw@df.com, 1, 风衣精, 1965 <== Total: 1 Monster{id=3, age=51, name='风衣精', email='qwrw@df.com', birthday=Sat Sep 12 00:00:00 CST 4015, salary=1965.0, gender=1} 查询第2次 Cache Hit Ratio [com.nlc.mapper.MonsterMapper]: 0.0 Monster{id=3, age=51, name='风衣精', email='qwrw@df.com', birthday=Sat Sep 12 00:00:00 CST 4015, salary=1965.0, gender=1} 查询第3次 Cache Hit Ratio [com.nlc.mapper.MonsterMapper]: 0.0 Monster{id=3, age=51, name='风衣精', email='qwrw@df.com', birthday=Sat Sep 12 00:00:00 CST 4015, salary=1965.0, gender=1} Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1cf56a1c] Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1cf56a1c] Returned connection 485845532 to pool. 操作成功
😄总结
- 缓存执行顺序是:二级缓存–>一级缓存–>数据库
- 二级缓存(数据)是在一级缓存关闭之后才有的。
- 二级缓存和一级缓存都是为了提高检索效率的技术,最大的区别就是作用域的范围不一样。
- 一级缓存的作用域是sqlSession 会话级别,在一次会话有效,而二级缓存作用域是全局范围,针对不同的会话都有效。
文章到这里就结束了,如果有什么疑问的地方请指出,诸大佬们一起来评论区一起讨论😁
希望能和诸大佬们一起努力,今后我们一起观看感谢您的阅读🍻
如果帮助到您不妨3连支持一下,创造不易您们的支持是我的动力🤞