Mybatis执行过程源码解析

本文详细解释了MyBatis中如何通过sqlSession会话获取mapper的代理实例,利用一级和二级缓存的原理,以及在执行mapper方法时的SQL指令处理和缓存更新过程。
摘要由CSDN通过智能技术生成

总述

简单来说就是通过开启一个sqlSession会话,通过jdk的动态代理方法获取对应mapper的代理实例对象,然后通过这个代理对象的invoke()方法执行MapperMethod对象方法。因为sqlSession之间一级缓存是隔离的,所以开启多个sqlSession后各自的一级缓存内容池是不一样的。invoke()执行后会根据id生成一个key,先去一级缓存查询有无对应key的缓存结果,如果没有就去执行DB操作查询解析出的sql结果,然后先移除缓存再插入。mybatis是如何知道我这个方法是delete/select/insert/update呢?这个是在执行invoke()时会讲mapper对应的xml配置文件传入的,它会解析这个方法对应的sqlType。具体可以看一下下面的解析过程。
在这里插入图片描述
在这里插入图片描述

第一阶段获取mapper动态代理阶段

    @Test
    public void testSecondCache() {
        User user4 = userMapper.getUserById(2L);
        System.out.println("----真实查询-----user4 = " + user4 + "\n");
        sqlSession.commit(); //当使用二级缓存的时候,只有调用了commit方法后才会生效。

        User user5 = userMapper.getUserById(2L);
        System.out.println("----缓存查询-----user5 = " + user5 + "\n");
		// 开启了新的sqlSession,则无法利用一级缓存,因为一级缓存是sqlSession之间隔离的
        sqlSession = SqlSessionFactoryUtil.openSqlSession();
        //开启新的sqlSession后,正式开始执行mybatis的过程,解析如下两行 
        userMapper = sqlSession.getMapper(UserMapper.class);
        User user6 = userMapper.getUserById(2L);
        System.out.println("----缓存查询-----user6 = " + user6);
    }

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

第二阶段获取mapperMethod对象

在这里插入图片描述

    @Test
    public void testSecondCache() {
        User user4 = userMapper.getUserById(2L);
        System.out.println("----真实查询-----user4 = " + user4 + "\n");
        sqlSession.commit(); //当使用二级缓存的时候,只有调用了commit方法后才会生效。

        User user5 = userMapper.getUserById(2L);
        System.out.println("----缓存查询-----user5 = " + user5 + "\n");

        sqlSession = SqlSessionFactoryUtil.openSqlSession(); 
        userMapper = sqlSession.getMapper(UserMapper.class);
        //通过第一阶段获取的mapper代理实例对象,执行代理的invoke方法(代理对象必须从invoke()方法执行)
        User user6 = userMapper.getUserById(2L);
        System.out.println("----缓存查询-----user6 = " + user6);
    }

第三阶段根据sql指令跳转执行语句

在这里插入图片描述

第四阶段查询前的缓存处理

在这里插入图片描述

//获取缓存key后从一级缓存中查询是否有结果,有就返回没有就执行db查询如何更新缓存
    public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
        Cache cache = ms.getCache();
        if (cache != null) {
            this.flushCacheIfRequired(ms);
            if (ms.isUseCache() && resultHandler == null) {
                this.ensureNoOutParams(ms, parameterObject, boundSql);
                List<E> list = (List)this.tcm.getObject(cache, key);
                if (list == null) {
                    list = this.delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
                    this.tcm.putObject(cache, key, list);
                }

                return list;
            }
        }

        return this.delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
    }

在这里插入图片描述
在这里插入图片描述

  • 10
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值