MP 启动注入 SQL 原理分析
文章目录
- 一、MybatisPlus需要sql语句吗?
- 解答:需要
- 1.1. 问题:为什么MybatisPlus看不到sql语句?
- 1.2. 分析:继承关系
- 1.3. 假设:操作数据库一定有sql
- 二、通过现象看本质
- 2.1. 测试案例
- 2.2. debug调试运行
- 2.2.1. employeeMapper的本质
- 2.2.2. MapperProxy中的对象
- 2.2.3. sqlSessionFactory中的对象
- 2.2.4. configuration对象
- 2.2.5. 方法对应关系
- 2.2.6. MP在启动的时候
- 2.2.7. 当我们调用方法的时候
- 三、源码分析:
- 3.1. 根据方法找到类
- 3.2 断点调试
- 3.3. 接着调用addDeleteMappedStatement
- 3.4. 调用injectDeleteByIdSql
- 3.5. sqlSource拼接完成
- 3.5. sqlSource拼接完成,继续调用删除方法
一、MybatisPlus需要sql语句吗?
解答:需要
1.1. 问题:为什么MybatisPlus看不到sql语句?
1.2. 分析:继承关系
- xxxMapper继承了BaseMapper,BaseMapper提供了通用的CRUD方法,
1.3. 假设:操作数据库一定有sql
- 方法来源于BaseMapper,有方法就必须有SQL,因为Mybatis最终还是需要通过SQL语句里操作数据库。
二、通过现象看本质
2.1. 测试案例
@Testpublic void testCommonSelect() {//1. 根据主键ID查询Integer idPK = 1;Employee employee = employeeMapper.selectById(idPK);System.out.println(employee);}
2.2. debug调试运行
employeeMapper就是一个接口,但是我们拿到的对象是一个代理对象,这个JDK动态代理
2.2.1. employeeMapper的本质
- 就是org.apache.ibatis.binding.MapperProxy@4362d7df
2.2.2. MapperProxy中的对象
- MapperProxy中sqlSeaaion有一个sqlSessionFactory
2.2.3. sqlSessionFactory中的对象
- 在sqlSessionFactory中有一个重要的对象configuration
2.2.4. configuration对象
- 这个对象是mybatis的全局配置对象,它包含了所有的配置信息。
- 在configuration里面有一个mappendStatements对象,它里面每一个都是一个mappendStatement
其实,每一个都是一个mapperdStatement都表示Mapper接口的一个方法与Mapper映射文件中的一个sql语句。
2.2.5. 方法对应关系
- 在BaseMapper定义的每一个方法,都会有一条sql语句与之对应mapperdStatement。
2.2.6. MP在启动的时候
- 就会分析已经把我们BaseMapper里面的每一个方法,,将来索要执行的sql语句,都帮我们构造好了,并且都帮我们都保存到了configuraion里面的MappedStatements中的MappedStatement了。
2.2.7. 当我们调用方法的时候
- 它就会回到configuration里面找到我们的MappedStatements,然后根据调用方法的名字,再去找到对应的sql语句,在其执行。
本质
在控制台,在实例化employeeMapper这个bean的时候,都调用了addMappedStatement这个方法,来添加一个addMappedStatement,而每一个addMappedStatement对应着mapper文件中的每一个方法
DEBUG 07-13 18:57:00,780 Autowiring by type from bean name 'employeeMapper' via property 'sqlSessionFactory' to bean named 'sqlSessionFactoryBean' (AbstractAutowireCapableBeanFactory.java:1349)
三、源码分析:
3.1. 根据方法找到类
根据addMappedStatement,找到此方法的类AutoSqlInjector SQL 自动注入器,
这个java文件
这个.class文件
3.2 断点调试
- 在.class文件中的addMappedStatement方法上打断点,dubug运行,当F8走到此方时,参数包括sqlSource 等都是前面传过来的,因此,我们需要往前推
3.3. 接着调用addDeleteMappedStatement
3.4. 调用injectDeleteByIdSql
3.5. sqlSource拼接完成
3.5. sqlSource拼接完成,继续调用删除方法
- 接下来就去调用addDeleteMappedStatement进行具体操作