zoukankan      html  css  js  c++  java
  • 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
    

    一级缓存 脏读问题

  • 相关阅读:
    ADO之connection
    函数及自定义函数
    母版页
    XHTML5 与 HTML 4.01的差异
    三层架构的使用
    ExecuteNonQuery&& ExecuteQuery 区别
    常用数据结构的时间复杂度
    图像处理(卷积)作者太棒了
    C#中标准Dispose模式的实现
    计算机网络知识点
  • 原文地址:https://www.cnblogs.com/zhenghengbin/p/13195727.html
Copyright © 2011-2022 走看看