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

zhenghengbin 2021-11-29 原文


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

一级缓存 脏读问题

发表于
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. 科学发明家特斯拉传记 – exce4

    科学发明家特斯拉传记 科学发明家特斯拉传记 //为了方便阅读,所以我根据矿业大学的PDF版本,使用<汉王 […]...

  2. office2010中word总是出现配置进度框的解决方案 – 全袁君

    office2010中word总是出现配置进度框的解决方案        相信学习电脑的人,每个人都使用过微软 […]...

  3. 微信公众平台注册 – 岚之山

    微信公众平台注册 微信公众平台是由腾讯公司开发,其宗旨是在移动互联网时代,让企业和个人以更简捷的形式提供服务给 […]...

  4. 牛客(牛牛与数组 )

    链接:https://ac.nowcoder.com/acm/problem/21738来源:牛客网 牛牛喜欢 […]...

  5. redhat双网关静态路由的问题解决方法(linux 路由表;linux增加路由表) – 季枫

    由于系统需要分别从内外网访问,即外网用户从外网访问服务器,内网用户从内网访问服务器,结果在配置双网关后发现内网 […]...

  6. 搞懂分布式技术30:高并发解决方案——提升高并发量服务器性能解决思路 – xiaok1024

    搞懂分布式技术30:高并发解决方案——提升高并发量服务器性能解决思路 2019-03-07 21:12  xi […]...

  7. 用Flood测试Web服务器响应时间 – 两颗番茄

    用Flood测试Web服务器响应时间 当你设置好服务器投入使用后,你最关心的事莫过于服务器的性能了。你可以用一 […]...

  8. MicroFocus推出手机自动化测试工具 – Silk Mobile – TIB

    MicroFocus推出手机自动化测试工具 – Silk Mobile MicroFocus推出手 […]...

随机推荐

  1. linux – 查看 python 版本

    命令 python -V   结果  ...

  2. 折纸问题

    微软原题 请把一段纸条竖着放在桌子上,然后从纸条的下边向上方对折1次,压出折痕后展开。此时折痕是凹下去的,即折 […]...

  3. jQuery 动画效果

    动画效果 目录 动画效果 1. 基本效果 2. 滑动效果 3 淡入淡出效果 4 自定义动画 5 动画控制 6 […]...

  4. 利用bak文件恢复数据库问题小结

    对备份的基础理解: –完整备份:完整备份会备份所有数据的区和少量的日志(日志文件用于恢复数据保持数 […]...

  5. mac charles抓安卓(小米)http包

    网上有很多的教程说明如何操作,都写的很好,比如 https://blog.csdn.net/luochouda […]...

  6. Transformer详解

    0 简述 Transformer改进了RNN最被人诟病的训练慢的缺点,利用self-attention机制实现 […]...

  7. MFC六大核心机制

     MFC六大核心机制概述        我们选择了C++,主要是因为它够艺术、够自由,使用它我们可以实现各种想 […]...

  8. 知识堂:汽车名词解释-变速箱/制动参数

    ● 变速箱名称 变速箱是由变速传动机构和操纵机构组成,就是用来传递发动机的输出动力,能变换齿轮的组合以应付不同 […]...

展开目录

目录导航