MyBatis 执行流程

候选人小严在面试阿里 P6 时,面试官问道:

"MyBatis 的执行流程是什么?"

小严说:"先解析 XML,然后创建 SqlSession..."

面试官追问:"SqlSession 是怎么拿到 Mapper 的?"

小严说:"通过 getMapper..."

面试官:"那 getMapper 返回的是什么东西?"

小严说:"代理对象?"

面试官:"代理对象是怎么创建的?InvocationHandler 做了什么?"

小严答不上来。

【面试官心理】 这道题我用来测试候选人对 MyBatis 核心原理的理解。MyBatis 的执行流程从 SqlSession 到 Mapper 代理到 StatementHandler,是 Java 面试中的高频题。能说清完整调用链的,基本都研究过 MyBatis 源码。


一、核心问题 🔴

1.1 问题拆解

第一层:核心组件

  • "MyBatis 有哪些核心组件?"
  • "SqlSession、Executor、StatementHandler 分别是什么?"

第二层:调用链路

  • "从调用 Mapper 方法到执行 SQL 的完整流程是什么?"
  • "getMapper 返回的代理对象是怎么工作的?"

第三层:细节

  • "Executor 有哪几种?区别是什么?"
  • "StatementHandler 是怎么拼装 SQL 的?"

1.2 标准回答

P5 回答:完整流程

MyBatis 执行流程:

1. 获取 SqlSessionFactory
   └─ 从配置文件/类创建 SqlSessionFactoryBuilder
       └─ XMLConfigBuilder.parse() 解析配置
           └─ 创建 Configuration

2. 获取 SqlSession
   └─ sqlSessionFactory.openSession()
       └─ 创建 Executor
       └─ 创建 DefaultSqlSession

3. 获取 Mapper
   └─ sqlSession.getMapper(UserMapper.class)
       └─ MapperProxyFactory.newInstance()
           └─ JDK/CGLIB 代理对象

4. 执行 Mapper 方法
   └─ mapper.selectById(1)
       └─ MapperProxy.invoke()
           └─ MapperMethod.execute()
               └─ SqlSession.selectOne()
                   └─ Executor.query()
                       └─ StatementHandler.query()
                           └─ PreparedStatement.execute()
                               └─ ResultSetHandler.handle()
                                   └─ 返回结果

1.3 追问升级

追问 1:Executor 的类型

// BaseExecutor - 基础执行器
// CachingExecutor - 缓存执行器(装饰器模式)

// openSession() 的参数决定用哪种执行器
SqlSession openSession(); // 默认:SimpleExecutor
SqlSession openSession(boolean autoCommit);
SqlSession openSession(ExecutorType execType);
SqlSession openSession(TransactionIsolationLevel level);
SqlSession openSession(ExecutorType execType, boolean autoCommit);
SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);
SqlSession openSession(ExecutorType execType, Connection connection);

ExecutorType:
- SIMPLE: 每次执行创建新的 PreparedStatement
- REUSE: 复用 PreparedStatement
- BATCH: 批量执行 SQL(用于 insert/update)
执行器特点适用场景
SimpleExecutor每次都创建新的 PreparedStatement简单查询
ReuseExecutor复用 PreparedStatement重复执行类似 SQL
BatchExecutor批量执行批量插入/更新

追问 2:StatementHandler 的职责

// StatementHandler 的继承体系
StatementHandler (接口)
  └─ RoutingStatementHandler  // 路由,根据语句类型选择
      └─ SimpleStatementHandler
      └─ PreparedStatementHandler  // 最常用
      └─ CallableStatementHandler

// PreparedStatementHandler 执行流程
public <E> List<E> query(Statement statement, ResultHandler resultHandler) {
    PreparedStatement ps = (PreparedStatement) statement;
    ps.execute(); // 执行 SQL
    return resultSetHandler.handleResultSets(ps); // 处理结果集
}

二、面试总结

MyBatis 执行流程的核心是 SqlSession → Executor → StatementHandler → PreparedStatement → ResultSetHandler 的完整链路。