MyBatis源码解析:从 Mapper 接口到 SQL 执行的完整链路
- 一、Mapper 代理对象的创建:sqlSession.getMapper(UserMapper.class)
- 二、接口方法的执行:mapper.selectUser("coderzpw", 18)
- 2.1 四大核心组件解析
- 2.1.1 Executor(执行器):流程控制核心
- 2.1.2 StatementHandler(语句处理器):JDBC 操作封装
- 2.1.3 ParameterHandler(参数处理器):参数解析与绑定
- 2.1.4 ResultSetHandler(结果集处理器):对象映射引擎
- 2.2 源码解析-完整调用链路:从 Mapper 方法到结果集的全流程
- 2.2.1 调用链路步骤分解
- 2.2.2 关键源码串联(MyBatis 3.4.6 版本)
- 步骤 1:Mapper 代理对象处理方法调用
- 步骤 2:SqlSession 委托 Executor 执行查询
- 步骤 3:Executor 执行查询(以 SimpleExecutor 为例)
- 步骤 4:创建 StatementHandler(RoutingStatementHandler)
- 步骤 5:StatementHandler 准备 Statement
- 步骤 6:ParameterHandler 设置参数
- 步骤 7:StatementHandler 执行查询
- 步骤 8:ResultSetHandler 处理结果集
MyBatis
的底层本质是对 JDBC
的封装,因此建议忘记 JDBC
执行流程的同学回顾相关知识。可参考这篇文章:【JDBC 核心执行流程详解】
在 MyBatis
中,常用的查询方式是通过 Mapper
接口代理实现,而非直接调用 sqlSession.selectList
例如:
// Mapper 接口定义
public interface UserMapper {
List<User> selectUser(@Param("name") String name, @Param("age") Integer age);
}
// 应用层调用(通过代理对象执行)
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.selectUser("coderzpw", 18); // 核心:代理对象处理方法调用
接下来文章内容主要围绕上述代码的底层源码逻辑展开讲解
一、Mapper 代理对象的创建:sqlSession.getMapper(UserMapper.class)
当调用 sqlSession.getMapper(UserMapper.class)
时,MyBatis
通过 MapperProxyFactory
创建动态代理对象,涉及到源码如下:
// DefaultSqlSession.java
public <T> T getMapper(Class<T> type) {
return configuration.<T>getMapper(type, this);
}
// Configuration.java
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
return mapperRegistry.getMapper(type, sqlSession);
}
// MapperRegistry.java
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
// 从已知的Mapper映射中查找对应的Mapper代理工厂
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
// 如果找不到对应的Mapper代理工厂,抛出绑定异常
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
}
try {
// 使用代理工厂创建Mapper代理实例
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
// MapperProxyFactory.java
public T newInstance(SqlSession sqlSession) {
// 创建Mapper代理处理器,它实现了InvocationHandler接口
// 参数1:当前SqlSession,用于执行SQL语句
// 参数2:Mapper接口类型
// 参数3:方法缓存,用于缓存Mapper方法对应的SQL语句
final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
protected T newInstance(MapperProxy<T> mapperProxy) {
// 使用JDK动态代理创建代理对象
// 参数1:类加载器,使用Mapper接口的类加载器
// 参数2:代理对象要实现的接口,这里就是Mapper接口
// 参数3:代理对象的调用处理器,负责处理代理对象方法的调用
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
梳理源码逻辑后,执行到 UserMapper mapper = sqlSession.getMapper(UserMapper.class)
时,MyBatis
通过动态代理为 UserMapper
接口生成代理对象,该对象会在后续数据访问中把接口方法调用转为 SQL
执行流程。
二、接口方法的执行:mapper.selectUser(“coderzpw”, 18)
2.1 四大核心组件解析
后续查询由 MyBatis
四大核心组件协同完成:
- Executor(执行器):控制整体查询流程
- StatementHandler(语句处理器):准备并执行
SQL
- ParameterHandler(参数处理器):处理
SQL
参数设置 - ResultSetHandler(结果集处理器):将查询结果映射为
Java
对象
2.1.1 Executor(执行器):流程控制核心
类层级:
Executor(接口)
├─ BaseExecutor(抽象类,实现一级缓存 + 事务管理)
│ ├─ SimpleExecutor(默认执行器,每次创建新 Statement)
│ ├─ ReuseExecutor(复用 Statement,基于 SimpleExecutor 扩展)
│ └─ BatchExecutor(批量执行,基于 SimpleExecutor 扩展)
└─ CachingExecutor(二级缓存装饰器,包装 Executor 实现缓存)
关键方法:query
(处理查询)、update
(处理更新)
核心源码片段(BaseExecutor
):
public abstract class BaseExecutor implements Executor {
// 一级缓存(本地缓存)
private final PerpetualCache localCache = new PerpetualCache("LocalCache");
// 占位符对象,用于标记正在执行的查询
private static final Object EXECUTION_PLACEHOLDER = new Object();
@Override
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) {
BoundSql boundSql = ms.getBoundSql(parameter);
// 生成缓存键(基于 SQL、参数、RowBounds 等)
CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
// ...
List<E> list;
try {
queryStack++;
// 从本地缓存获取结果
list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
// 如果缓存命中,处理本地缓存的输出参数(如存储过程的OUT参数)
if (list != null) {
handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
} else {
// 缓存未命中,从数据库查询并缓存结果
list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
} finally {
queryStack--;
}
// ...
// 返回查询结果列表
return list;
}
private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) {
List<E> list;
// 先在缓存中放入占位符,标记该查询正在执行
localCache.putObject(key, EXECUTION_PLACEHOLDER);
try {
// 执行实际的数据库查询
list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
} finally {
// 移除占位符
localCache.removeObject(key);
}
// 将实际查询结果存入缓存
localCache.putObject(key, list);
// 处理存储过程的输出参数(本文示例不涉及)
if (ms.getStatementType() == StatementType.CALLABLE) {
localOutputParameterCache.putObject(key, parameter);
}
return list;
}
// 子类实现具体执行逻辑(如 SimpleExecutor 的 doQuery)
protected abstract <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException;
}
2.1.2 StatementHandler(语句处理器):JDBC 操作封装
类层级:
StatementHandler(接口)
├─ BaseStatementHandler(抽象类,实现公共逻辑)
│ ├─ SimpleStatementHandler(处理普通 Statement,无参数)
│ ├─ PreparedStatementHandler(处理预编译 PreparedStatement,带参数)
│ └─ CallableStatementHandler(处理存储过程 CallableStatement)
└─ RoutingStatementHandler(路由类,不直接处理 SQL,仅根据 StatementType 选择具体实现)
关键方法:prepare
(创建 Statement
)、parameterize
(设置参数)、query
(执行查询)
核心源码片段(BaseExecutor
):
public class PreparedStatementHandler extends BaseStatementHandler {
public PreparedStatementHandler(Executor executor, MappedStatement ms,
Object parameter, RowBounds rowBounds,
ResultHandler resultHandler, BoundSql boundSql) {
super(executor, ms, parameter, rowBounds, resultHandler, boundSql);
}
// 创建预编译 Statement
@Override
protected Statement instantiateStatement(Connection connection) throws SQLException {
String sql = boundSql.getSql();
// 处理需要返回自动生成键的情况(如INSERT语句)
if (mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) {
String[] keyColumnNames = mappedStatement.getKeyColumns();
if (keyColumnNames == null) {
// 如果没有指定主键列名,使用默认方式返回所有生成的键
return connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
} else {
// 如果指定了主键列名,只返回这些列的生成键
return connection.prepareStatement(sql, keyColumnNames);
}
}
// 处理需要指定结果集类型的情况
else if (mappedStatement.getResultSetType() != null) {
return connection.prepareStatement(
sql,
mappedStatement.getResultSetType().getValue(),
ResultSet.CONCUR_READ_ONLY // 设置结果集为只读
);
}
// 默认情况,使用标准的PreparedStatement
else {
return connection.prepareStatement(sql);
}
}
// 执行查询并处理结果集
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
// 执行 SQL
ps.execute();
// 委托 ResultSetHandler 处理结果集
return resultSetHandler.handleResultSets(ps);
}
}
2.1.3 ParameterHandler(参数处理器):参数解析与绑定
实现类:DefaultParameterHandler
关键逻辑:将方法参数(如 name
和 age
)映射到 SQL 占位符(?
),通过 TypeHandler
转换类型
核心源码片段:
public void setParameters(PreparedStatement ps) {
// 设置错误上下文,记录当前活动为"设置参数",并关联到对应的参数映射ID
ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
// 获取SQL语句中的参数映射列表
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
// 遍历参数映射列表,为每个参数设置值
if (parameterMappings != null) {
for (int i = 0; i < parameterMappings.size(); i++) {
ParameterMapping parameterMapping = parameterMappings.get(i);
// 仅处理输入参数(IN或INOUT),忽略输出参数(OUT)
if (parameterMapping.getMode() != ParameterMode.OUT) {
Object value;
String propertyName = parameterMapping.getProperty();
// 1. 首先检查是否为额外参数(如动态SQL中定义的参数)
if (boundSql.hasAdditionalParameter(propertyName)) {
value = boundSql.getAdditionalParameter(propertyName);
}
// 2. 检查参数对象是否为null
else if (parameterObject == null) {
value = null;
}
// 3. 检查参数对象是否可以直接使用类型处理器处理(如基本类型)
else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
value = parameterObject;
}
// 4. 对于复杂对象,使用MetaObject反射获取属性值
else {
MetaObject metaObject = configuration.newMetaObject(parameterObject);
value = metaObject.getValue(propertyName);
}
// 获取参数的类型处理器和JDBC类型
TypeHandler typeHandler = parameterMapping.getTypeHandler();
JdbcType jdbcType = parameterMapping.getJdbcType();
// 处理null值的JDBC类型
if (value == null && jdbcType == null) {
jdbcType = configuration.getJdbcTypeForNull();
}
try {
// 使用类型处理器将Java对象转换为JDBC参数并设置到PreparedStatement中
// 注意:JDBC参数索引从1开始,而不是从0开始
typeHandler.setParameter(ps, i + 1, value, jdbcType);
} catch (TypeException e) {
throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
} catch (SQLException e) {
throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
}
}
}
}
}
2.1.4 ResultSetHandler(结果集处理器):对象映射引擎
实现类:DefaultResultSetHandler
关键逻辑:将 ResultSet
逐行映射为 Java 对象,支持 ResultMap
配置的字段到属性映射
核心源码片段:
public List<Object> handleResultSets(Statement stmt) throws SQLException {
// 存储所有结果
List<Object> results = new ArrayList<>();
// 获取第一个结果集
ResultSetWrapper rsw = getFirstResultSet(stmt);
List<ResultMap> resultMaps = mappedStatement.getResultMaps();
// 处理主结果集
for (ResultMap resultMap : resultMaps) {
if (rsw == null) break;
handleResultSet(rsw, resultMap, results, null);
rsw = getNextResultSet(stmt);
// ...清理资源
}
// 处理命名结果集(如存储过程返回的多个结果集)
String[] resultSets = mappedStatement.getResultSets();
if (resultSets != null) {
for (String resultSet : resultSets) {
if (rsw == null) break;
ResultMapping mapping = nextResultMaps.get(resultSet);
if (mapping != null) {
ResultMap nestedMap = configuration.getResultMap(mapping.getNestedResultMapId());
handleResultSet(rsw, nestedMap, null, mapping);
}
rsw = getNextResultSet(stmt);
// ...清理资源
}
}
// 整理结果
return collapseSingleResultList(results);
}
private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException {
try {
// 处理嵌套结果映射(如一对多关系)
if (parentMapping != null) {
handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping);
}
// 处理普通结果集
else {
// 使用默认结果处理器收集结果
if (resultHandler == null) {
DefaultResultHandler defaultHandler = new DefaultResultHandler(objectFactory);
handleRowValues(rsw, resultMap, defaultHandler, rowBounds, null);
multipleResults.add(defaultHandler.getResultList());
}
// 使用自定义结果处理器
else {
handleRowValues(rsw, resultMap, resultHandler, rowBounds, null);
}
}
} finally {
// 关闭结果集
closeResultSet(rsw.getResultSet());
}
}
2.2 源码解析-完整调用链路:从 Mapper 方法到结果集的全流程
接下来聚焦 List<User> users = mapper.selectUser("coderzpw", 18)
调用,执行时通过代理对象触发 MapperProxy
的 invoke
方法,进而调用 MapperMethod
的 execute
方法,MyBatis
会依方法签名和参数确定并转换 SQL
。
2.2.1 调用链路步骤分解
Mapper接口方法调用(如UserMapper.selectUser(name, age))
├─ 【MapperProxy(代理对象)】
│ ├─ 拦截接口方法调用,触发 invoke() 方法
│ ├─ 从缓存中获取对应的 MapperMethod 对象
│ └─ 调用 mapperMethod.execute(sqlSession, args)
│
├─ 【MapperMethod】
│ ├─ 根据方法类型(SELECT/INSERT/UPDATE/DELETE)选择执行策略
│ ├─ 解析方法参数,构建参数对象
│ └─ 调用 sqlSession 对应方法(如 selectList/selectOne/insert 等)
│
├─ 【DefaultSqlSession】
│ └─ 委托 Executor.query() 执行查询(Executor 组件)
│
├─ 【Executor(SimpleExecutor)】
│ ├─ 创建 StatementHandler(PreparedStatementHandler)
│ ├─ 调用 handler.prepare() 创建 PreparedStatement(含预编译 SQL)
│ ├─ 调用 handler.parameterize() 触发 ParameterHandler 设置参数
│ └─ 调用 handler.query() 执行 SQL,获取 ResultSet
│
├─ 【StatementHandler(PreparedStatementHandler)】
│ ├─ instantiateStatement() 创建 PreparedStatement(SQL: "select * from user where name = ? and age > ?")
│ ├─ setParameters() 委托 ParameterHandler 绑定参数(name=? 对应 "张三",age=? 对应 20)
│ └─ execute() 执行查询,返回 ResultSet 给 ResultSetHandler
│
├─ 【ParameterHandler(DefaultParameterHandler)】
│ └─ setParameters() 遍历参数映射,通过 TypeHandler 转换并设置到 PreparedStatement
│
└─ 【ResultSetHandler(DefaultResultSetHandler)】
├─ handleResultSets() 遍历 ResultSet 行
├─ createResultObject() 创建 User 实例
└─ 通过反射将列值(name、age 等)设置到 User 对象属性
2.2.2 关键源码串联(MyBatis 3.4.6 版本)
步骤 1:Mapper 代理对象处理方法调用
// MapperProxy.java
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
// 处理 Object 类的通用方法(如 toString、equals 等)
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
}
// 处理 Java 8 引入的接口默认方法
else if (isDefaultMethod(method)) {
return invokeDefaultMethod(proxy, method, args);
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
// 对 Mapper 接口定义的方法进行缓存和执行
final MapperMethod mapperMethod = cachedMapperMethod(method);
// 执行实际的数据库操作
return mapperMethod.execute(sqlSession, args);
}
// MapperMethod.java
public Object execute(SqlSession sqlSession, Object[] args) {
Object result;
// 根据 SQL 命令类型选择执行方法
switch (command.getType()) {
case INSERT: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.insert(command.getName(), param));
break;
}
case UPDATE: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.update(command.getName(), param));
break;
}
case DELETE: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.delete(command.getName(), param));
break;
}
case SELECT:
// 处理返回值为 void 且有 ResultHandler 的情况
if (method.returnsVoid() && method.hasResultHandler()) {
executeWithResultHandler(sqlSession, args);
result = null;
}
// 处理返回值为集合的情况
else if (method.returnsMany()) {
result = executeForMany(sqlSession, args);
}
// 处理返回值为 Map 的情况
else if (method.returnsMap()) {
result = executeForMap(sqlSession, args);
}
// 处理返回值为 Cursor 的情况
else if (method.returnsCursor()) {
result = executeForCursor(sqlSession, args);
}
// 处理返回单个对象的情况
else {
Object param = method.convertArgsToSqlCommandParam(args);
result = sqlSession.selectOne(command.getName(), param);
// 处理返回值为 Optional 的情况
if (method.returnsOptional() && (result == null || !method.getReturnType().equals(result.getClass()))) {
result = Optional.ofNullable(result);
}
}
break;
case FLUSH:
result = sqlSession.flushStatements();
break;
default:
throw new BindingException("Unknown execution method for: " + command.getName());
}
// 处理返回值为 null 但不允许 null 的情况
if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
throw new BindingException("Mapper method '" + command.getName()
+ " attempted to return null from a method with a primitive return type ("
+ method.getReturnType() + ").");
}
return result;
}
// 处理多参数情况,将参数转换为 SQL 参数
public Object convertArgsToSqlCommandParam(Object[] args) {
// 无参数
if (args == null || args.length == 0) {
return null;
}
// 单个参数且无 @Param 注解
else if (args.length == 1 && !hasNamedParameters) {
return args[0];
}
// 多个参数或有 @Param 注解
else {
final Map<String, Object> param = new ParamMap<>();
int i = 0;
// 处理 @Param 注解的参数
for (String name : paramNames) {
param.put(name, args[i++]);
}
// 为参数添加 param1, param2 等键
if (paramNames.size() < args.length) {
for (int j = paramNames.size(); j < args.length; j++) {
param.put("param" + String.valueOf(j + 1), args[j]);
}
}
return param;
}
}
步骤 2:SqlSession 委托 Executor 执行查询
// DefaultSqlSession.java
@Override
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
try {
// 根据 statement ID 获取 MappedStatement
MappedStatement ms = configuration.getMappedStatement(statement);
// 委托 Executor 执行查询
return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
// 处理集合参数
private Object wrapCollection(final Object object) {
if (object instanceof Collection) {
StrictMap<Object> map = new StrictMap<>();
map.put("collection", object);
if (object instanceof List) {
map.put("list", object);
}
return map;
} else if (object != null && object.getClass().isArray()) {
StrictMap<Object> map = new StrictMap<>();
map.put("array", object);
return map;
}
return object;
}
步骤 3:Executor 执行查询(以 SimpleExecutor 为例)
// BaseExecutor.java
@Override
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
// 获取 BoundSql(包含解析后的 SQL 和参数映射信息)
BoundSql boundSql = ms.getBoundSql(parameter);
// 创建缓存键(基于 SQL、参数、RowBounds 等)
CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
// 执行查询(可能从缓存获取)
return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
@Override
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
// 如果已关闭,抛出异常
if (closed) {
throw new ExecutorException("Executor was closed.");
}
// 先清空本地缓存(针对 select 语句,一级缓存会在查询前清空)
if (queryStack == 0 && ms.isFlushCacheRequired()) {
clearLocalCache();
}
List<E> list;
try {
queryStack++;
// 从本地缓存获取结果
list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
if (list != null) {
// 处理存储过程的输出参数
handleLocallyCachedOutputParameters(ms, key, parameter);
} else {
// 本地缓存未命中,执行数据库查询
list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
} finally {
queryStack--;
}
if (queryStack == 0) {
// 延迟加载队列处理
for (DeferredLoad deferredLoad : deferredLoads) {
deferredLoad.load();
}
// 清空延迟加载队列
deferredLoads.clear();
// 一级缓存的作用域是 session,默认情况下,select 语句执行后会清空本地缓存
if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
clearLocalCache();
}
}
return list;
}
// 从数据库查询
private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
List<E> list;
// 先在缓存中放入占位符,避免递归查询
localCache.putObject(key, EXECUTION_PLACEHOLDER);
try {
// 调用子类的 doQuery 方法执行实际查询
list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
} finally {
// 移除占位符
localCache.removeObject(key);
}
// 将查询结果放入缓存
localCache.putObject(key, list);
// 处理存储过程的输出参数
if (ms.getStatementType() == StatementType.CALLABLE) {
localOutputParameterCache.putObject(key, parameter);
}
return list;
}
// SimpleExecutor.java
@Override
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
Statement stmt = null;
try {
Configuration configuration = ms.getConfiguration();
// 创建 StatementHandler(路由到实际的 StatementHandler 实现)
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
// 准备 Statement
stmt = prepareStatement(handler, ms.getStatementLog());
// 执行查询
return handler.query(stmt, resultHandler);
} finally {
// 关闭 Statement
closeStatement(stmt);
}
}
// 准备 Statement
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Statement stmt;
// 获取数据库连接
Connection connection = getConnection(statementLog);
// 准备 Statement
stmt = handler.prepare(connection, transaction.getTimeout());
// 设置参数
handler.parameterize(stmt);
return stmt;
}
步骤 4:创建 StatementHandler(RoutingStatementHandler)
// Configuration.java
public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
// 创建 StatementHandler(实际创建的是 RoutingStatementHandler)
StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
// 应用插件(如果有)
statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
return statementHandler;
}
// RoutingStatementHandler.java
public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
// 根据 StatementType 选择实际的 StatementHandler 实现
switch (ms.getStatementType()) {
case STATEMENT:
delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
case PREPARED:
// 对于预编译语句,使用 PreparedStatementHandler
delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
case CALLABLE:
delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
default:
throw new ExecutorException("Unknown statement type: " + ms.getStatementType());
}
}
步骤 5:StatementHandler 准备 Statement
// BaseStatementHandler.java
@Override
public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
ErrorContext.instance().sql(boundSql.getSql());
Statement statement = null;
try {
// 实例化 Statement
statement = instantiateStatement(connection);
// 设置超时时间
setStatementTimeout(statement, transactionTimeout);
// 设置 fetchSize
setFetchSize(statement);
return statement;
} catch (SQLException e) {
closeStatement(statement);
throw e;
} catch (Exception e) {
closeStatement(statement);
throw new ExecutorException("Error preparing statement. Cause: " + e, e);
}
}
// PreparedStatementHandler.java
@Override
protected Statement instantiateStatement(Connection connection) throws SQLException {
String sql = boundSql.getSql();
// 获取主键生成策略
if (mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) {
String[] keyColumnNames = mappedStatement.getKeyColumns();
if (keyColumnNames == null) {
// 没有指定主键列,使用 JDBC 3.0 规范的方法获取自增主键
return connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
} else {
// 指定了主键列,使用指定的列获取自增主键
return connection.prepareStatement(sql, keyColumnNames);
}
} else if (mappedStatement.getResultSetType() != null) {
// 设置结果集类型
return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
} else {
// 默认情况,创建预编译语句
return connection.prepareStatement(sql);
}
}
步骤 6:ParameterHandler 设置参数
// BaseStatementHandler.java
@Override
public void parameterize(Statement statement) throws SQLException {
// 委托 ParameterHandler 设置参数
parameterHandler.setParameters((PreparedStatement) statement);
}
// DefaultParameterHandler.java
@Override
public void setParameters(PreparedStatement ps) {
ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
// 获取参数映射列表
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
if (parameterMappings != null) {
// 遍历参数映射
for (int i = 0; i < parameterMappings.size(); i++) {
ParameterMapping parameterMapping = parameterMappings.get(i);
// 处理非输出参数(存储过程可能有输出参数)
if (parameterMapping.getMode() != ParameterMode.OUT) {
Object value;
String propertyName = parameterMapping.getProperty();
// 处理动态参数(如 _parameter、_databaseId)
if (boundSql.hasAdditionalParameter(propertyName)) {
value = boundSql.getAdditionalParameter(propertyName);
}
// 处理参数为 null 的情况
else if (parameterObject == null) {
value = null;
}
// 处理参数为基本类型的情况
else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
value = parameterObject;
}
// 处理参数为对象或 Map 的情况
else {
MetaObject metaObject = configuration.newMetaObject(parameterObject);
value = metaObject.getValue(propertyName);
}
// 获取类型处理器
TypeHandler typeHandler = parameterMapping.getTypeHandler();
JdbcType jdbcType = parameterMapping.getJdbcType();
// 处理 jdbcType 为 null 的情况
if (value == null && jdbcType == null) {
jdbcType = configuration.getJdbcTypeForNull();
}
try {
// 设置参数(核心:类型处理器将 Java 对象转换为 JDBC 类型)
typeHandler.setParameter(ps, i + 1, value, jdbcType);
} catch (TypeException e) {
throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
} catch (SQLException e) {
throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
}
}
}
}
}
步骤 7:StatementHandler 执行查询
// PreparedStatementHandler.java
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
// 转换为 PreparedStatement
PreparedStatement ps = (PreparedStatement) statement;
// 执行 SQL
ps.execute();
// 委托 ResultSetHandler 处理结果集
return resultSetHandler.handleResultSets(ps);
}
步骤 8:ResultSetHandler 处理结果集
// DefaultResultSetHandler.java
@Override
public List<Object> handleResultSets(Statement stmt) throws SQLException {
ErrorContext.instance().activity("handling results").object(mappedStatement.getId());
final List<Object> multipleResults = new ArrayList<>();
int resultSetCount = 0;
// 获取第一个结果集
ResultSet rs = getFirstResultSet(stmt);
// 获取结果映射列表
List<ResultMap> resultMaps = mappedStatement.getResultMaps();
int resultMapCount = resultMaps.size();
// 验证结果映射数量
validateResultMapsCount(rs, resultMapCount);
// 处理所有结果集
while (rs != null && resultMapCount > resultSetCount) {
ResultMap resultMap = resultMaps.get(resultSetCount);
// 处理单个结果集
handleResultSet(rs, resultMap, multipleResults, null);
// 获取下一个结果集(适用于存储过程返回多个结果集的情况)
rs = getNextResultSet(stmt);
// 清理资源
cleanUpAfterHandlingResultSet();
resultSetCount++;
}
// 处理结果集映射
String[] resultSets = mappedStatement.getResultSets();
if (resultSets != null) {
while (rs != null && resultSetCount < resultSets.length) {
// 处理命名结果集
ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]);
if (parentMapping != null) {
String nestedResultMapId = parentMapping.getNestedResultMapId();
ResultMap resultMap = configuration.getResultMap(nestedResultMapId);
handleResultSet(rs, resultMap, null, parentMapping);
}
rs = getNextResultSet(stmt);
cleanUpAfterHandlingResultSet();
resultSetCount++;
}
}
// 处理单个结果集的情况,将其展开为列表
return collapseSingleResultList(multipleResults);
}
// 处理单个结果集
private void handleResultSet(ResultSet rs, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException {
try {
if (parentMapping != null) {
// 处理嵌套结果集
handleRowValues(rs, resultMap, null, RowBounds.DEFAULT, parentMapping);
} else {
// 处理普通结果集
if (resultHandler == null) {
// 创建默认结果处理器
DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);
// 处理行值
handleRowValues(rs, resultMap, defaultResultHandler, rowBounds, null);
// 将结果添加到多个结果列表中
multipleResults.add(defaultResultHandler.getResultList());
} else {
// 使用用户提供的结果处理器
handleRowValues(rs, resultMap, resultHandler, rowBounds, null);
}
}
} finally {
// 关闭结果集
closeResultSet(rs);
}
}
// 处理行值
private void handleRowValues(ResultSet rs, ResultMap resultMap, ResultHandler resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
if (resultMap.hasNestedResultMaps()) {
// 处理包含嵌套结果映射的情况
ensureNoRowBounds();
checkResultHandler();
handleRowValuesForNestedResultMap(rs, resultMap, resultHandler, rowBounds, parentMapping);
} else {
// 处理简单结果映射的情况
handleRowValuesForSimpleResultMap(rs, resultMap, resultHandler, rowBounds);
}
}
// 处理简单结果映射的行值
private void handleRowValuesForSimpleResultMap(ResultSet rs, ResultMap resultMap, ResultHandler resultHandler, RowBounds rowBounds) throws SQLException {
DefaultResultContext<Object> resultContext = new DefaultResultContext<>();
// 跳过分页偏移量
skipRows(rs, rowBounds.getOffset());
// 处理行数据
while (shouldProcessMoreRows(resultContext, rowBounds) && rs.next()) {
// 获取判别式结果映射(用于动态结果映射)
ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rs, resultMap, null);
// 获取行值(创建结果对象并填充数据)
Object rowValue = getRowValue(rs, discriminatedResultMap);
// 将行值添加到结果上下文中
resultContext.nextResultObject(rowValue);
// 如果有结果处理器,调用它处理结果
if (resultHandler != null) {
resultHandler.handleResult(resultContext);
}
}
}
// 获取行值(创建结果对象并填充数据)
private Object getRowValue(ResultSet rs, ResultMap resultMap) throws SQLException {
final ResultLoaderMap lazyLoader = new ResultLoaderMap();
// 创建结果对象
Object rowValue = createResultObject(rs, resultMap, lazyLoader, null);
if (rowValue != null && !resultMap.isPrimitive()) {
// 创建元对象
MetaObject metaObject = configuration.newMetaObject(rowValue);
// 标记是否找到值
boolean foundValues = this.useConstructorMappings;
// 处理自动映射
if (shouldApplyAutomaticMappings(resultMap, false)) {
foundValues = applyAutomaticMappings(rs, resultMap, metaObject, null) || foundValues;
}
// 处理手动映射
foundValues = applyPropertyMappings(rs, resultMap, metaObject, lazyLoader, null) || foundValues;
// 如果没有找到任何值且需要非空结果,则返回 null
foundValues = lazyLoader.size() > 0 || foundValues;
rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null;
}
return rowValue;
}
// 创建结果对象
private Object createResultObject(ResultSet rs, ResultMap resultMap, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException {
this.useConstructorMappings = false; // 重置构造函数映射标志
// 获取结果类型
final Class<?> resultType = resultMap.getType();
// 创建元对象处理器
final List<Class<?>> constructorArgTypes = new ArrayList<>();
final List<Object> constructorArgs = new ArrayList<>();
// 创建结果对象
Object resultObject = createResultObject(rs, resultType, constructorArgTypes, constructorArgs, columnPrefix);
// 如果结果类型不是基本类型
if (resultObject != null && !resultType.isInterface()) {
// 检查是否有构造函数映射
if (shouldApplyAutomaticMappings(resultMap, true)) {
// 应用自动映射
applyAutomaticMappings(rs, resultMap, configuration.newMetaObject(resultObject), columnPrefix);
}
// 应用属性映射
applyPropertyMappings(rs, resultMap, configuration.newMetaObject(resultObject), lazyLoader, columnPrefix);
}
// 标记使用了构造函数映射
this.useConstructorMappings = resultObject != null && !constructorArgTypes.isEmpty();
return resultObject;
}