mybatis缓存之一级缓存(二)
2020-06-26 17:50
471 查看
这篇文章介绍下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 200c [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 延迟加载,一级缓存,二级缓存设置
- mybatis的缓存机制(一级缓存二级缓存和刷新缓存)和mybatis整合ehcache
- Mybatis (七)延迟加载\一级缓存\二级缓存
- Mybatis一级缓存和二级缓存
- Mybatis一级缓存、二级缓存详讲
- mybatis教程--查询缓存(一级缓存二级缓存和整合ehcache)
- Mybatis的一级缓存和二级缓存的理解和区别
- Mybatis一级缓存和二级缓存
- MyBatis框架及源码分析(3)—— MyBatis的一级缓存及二级缓存
- Mybatis的一级缓存和二级缓存的理解和区别
- MyBatis的一级缓存和二级缓存简介笔记
- MyBatis一级缓存与二级缓存
- 【MyBatis框架】查询缓存-一级缓存原理
- mybatis 详解(九)------ 一级缓存、二级缓存
- MyBatis 系列五 之 延迟加载、一级缓存、二级缓存设置
- mybatis的延迟加载,一级缓存,二级缓存
- 【MyBatis】MyBatis一级缓存和二级缓存
- MyBatis(十一)——MyBatis缓存(一级缓存和二级缓存)