接下来,我们按照之前写的测试用例,使用debug来梳理一下mybatis的工作流程,测试用例如下:
package com.mybatis.mine;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.io.InputStream;
public class MineTest1 {
@Test
public void test01() throws IOException {
String resource = "com/mybatis/mine/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.selectUser("10");
System.out.println(user);
}
}
首先我们来跟踪SqlSessionFactory的创建:SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
经过debug跟踪,我们会发现这个流程的主要步骤如下:
org.apache.ibatis.session.SqlSessionFactoryBuilder#build(java.io.InputStream) //使用SqlSessionFactoryBuilder的build
>org.apache.ibatis.session.SqlSessionFactoryBuilder#build(java.io.InputStream, java.lang.String, java.util.Properties)
>org.apache.ibatis.builder.xml.XMLConfigBuilder#parse //加载配置文件,获取configuration对象
>org.apache.ibatis.builder.xml.XMLConfigBuilder#parseConfiguration
>org.apache.ibatis.builder.xml.XMLConfigBuilder#mapperElement //加载映射器
>org.apache.ibatis.session.Configuration#addMapper
>org.apache.ibatis.binding.MapperRegistry#addMapper
>org.apache.ibatis.builder.annotation.MapperAnnotationBuilder#parse //Annotation方式解析
>org.apache.ibatis.session.SqlSessionFactoryBuilder#build(org.apache.ibatis.session.Configuration) //生成SqlSessionFactory
也就是说在这里,mybatis主要做了加载配置文件、加载映射器、生成SqlSessionFactory等主要操作。
接下来我们来SqlSession的获取:SqlSession sqlSession = sqlSessionFactory.openSession();
org.apache.ibatis.session.SqlSessionFactory#openSession() //获取SqlSession
>org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSessionFromDataSource
>org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#getTransactionFactoryFromEnvironment //获取 TransactionFactory
>org.apache.ibatis.transaction.TransactionFactory#newTransaction(javax.sql.DataSource, org.apache.ibatis.session.TransactionIsolationLevel, boolean) //获取事务
>org.apache.ibatis.session.Configuration#newExecutor(org.apache.ibatis.transaction.Transaction, org.apache.ibatis.session.ExecutorType) // 生成Executor
>org.apache.ibatis.session.defaults.DefaultSqlSession //new DefaultSqlSession()
对于这一步,mybatis主要做的工作就是生成事务、创建执行器、最后生成SqlSession实例
对于UserMapper userMapper = sqlSession.getMapper(UserMapper.class);我们就不多赘述了,这个主要是从第一步的MapperRegistry中获取相应的Mapper
最后我们来看下具体的数据库操作流程:
org.apache.ibatis.binding.MapperProxy#invoke //动态代理
>org.apache.ibatis.binding.MapperMethod#execute
>org.apache.ibatis.session.SqlSession#selectOne(java.lang.String, java.lang.Object) //进行查询
>org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)
>org.apache.ibatis.session.Configuration#getMappedStatement(java.lang.String) //获取MappedStatement
>org.apache.ibatis.session.defaults.DefaultSqlSession#wrapCollection //解析参数
>org.apache.ibatis.executor.BaseExecutor#query() //真正的查询处理
>org.apache.ibatis.executor.BaseExecutor#queryFromDatabase
>org.apache.ibatis.executor.BaseExecutor#doQuery
>org.apache.ibatis.session.Configuration#newStatementHandler //生成StatementHandler
>org.apache.ibatis.executor.statement.StatementHandler#query //使用StatementHandler进行查询处理
>java.sql.PreparedStatement#execute //调用jdbc的execute方法
>org.apache.ibatis.executor.resultset.ResultSetHandler#handleResultSets //结果集处理
这一步mybatis首先通过动态代理,找到目标方法,然后使用相应的执行器进行数据库操作。在这一步中做了几点重要的处理:
- 获取目标方法
- 生成MappedStatement
- 装载参数
- 生成StatementHandler
- 调用StatementHandler中相应的方法,进行数据库操作
- 结果集处理
以上便是mybatis一个完整的处理流程,希望对大家有所启发。下面附两张图大致总结一下以上流程:
第一张图描述了从SqlSessionFactory创建到获取Mapper的一个流程:
第二张图描述了mybatis数据库操作的简易流程: