接下來,我們按照之前寫的測試用例,使用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數據庫操作的簡易流程: