MyBatis源码之MyBatis中SQL语句执行过程
SQL执行入口
我们在使用MyBatis编程时有两种方式:
方式一代码如下:
1 | java复制代码SqlSession sqlSession = sqlSessionFactory.openSession(); |
方式二代码如下:
1 | java复制代码SqlSession sqlSession = sqlSessionFactory.openSession(); |
方式一入口分析
方式一调用的是SqlSession接口的selectList方法:
执行的是DefaultSqlSession中的实现
经过多次重载后,调用的是此方法:
MappedStatement封装的是我们的SQL语句;
方法内部执行的是executor的query方法。
方法二入口分析
方法二调用的是SqlSession接口的getMapper(Class type)方法:
我们实际调用的是DefaultSqlSession实现类中的方法:
此方法内部又调用了
1 | java复制代码 configuration.<T>getMapper(type, this); |
最后调用了:
1 | java复制代码return mapperProxyFactory.newInstance(sqlSession); |
通过工厂创建了接口的代理对象。
Mapper接口动态代理
上面讲到会通过
1 | java复制代码 mapperProxyFactory.newInstance(sqlSession); |
来创建动态代理类;
那创建动态代理类会执行哪些方法呢?
可以看到有MapperProxy这个类,实际上都会执行MapperProxy类中的invoke方法。
invoke方法会先判断方法是不是Object的方法,如果是,就直接调用;否则会执行cachedInvoker()方法
cachedInvoker()的作用是获取缓存中MapperMethodInvoker,如果没有则创建一个,而MapperMethodInvoker内部封装了MethodHandler。
当cacheInvoker返回了PalinMethodInvoker实例之后,紧接着调用了这个实例的PlainMethodInvoker#invoke方法
然后就调用了execute()方法
里面调用了sqlSession的方法。
方法的调用关系如下:
1 | java复制代码MapperProxy#invoke()//代理对象执行的方法,代理后所有Mapper的方法调用时,都会调用这个invoke方法 |
SQL执行流程
查询SQL执行流程
主要步骤:
- selectOne/selectList
- SQL获取
- 参数设置
- SQL执行
- 封装结果集
调用关系如下:
1 | java复制代码DefaultSqlSession#selectOne()//执行单记录 |
增删改SQL执行流程
主要步骤
- insert|update|delete方法分析
- SQL获取
- 参数设置
- SQL执行
- 封装结果集
MyBatis中增删改的代码如下:
1 | java复制代码//DefaultSqlSession |
我们发现,增删改最后执行的都是update,这是因为insert、update、delete实际上都是对数据库中数据的改变。
执行流程为:
1 | java复制代码DefaultSqlSession#update() |
图示
最后我们画出执行的流程图如下:
本文转载自: 掘金