MyBatis源码解析:从 Mapper 接口到 SQL 执行的完整链路
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.javapublic 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();@Overridepublic <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@Overrideprotected 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 // 设置结果集为只读);} // 默认情况,使用标准的PreparedStatementelse {return connection.prepareStatement(sql);}}// 执行查询并处理结果集@Overridepublic <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {PreparedStatement ps = (PreparedStatement) statement;// 执行 SQLps.execute(); // 委托 ResultSetHandler 处理结果集return resultSetHandler.handleResultSets(ps);}
}
2.1.3 ParameterHandler(参数处理器):参数解析与绑定
实现类:DefaultParameterHandler
关键逻辑:将方法参数(如 name
和 age
)映射到 SQL 占位符(?
),通过 TypeHandler
转换类型
核心源码片段:
public void setParameters(PreparedStatement ps) {// 设置错误上下文,记录当前活动为"设置参数",并关联到对应的参数映射IDErrorContext.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. 检查参数对象是否为nullelse 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 获取 MappedStatementMappedStatement 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);// 准备 Statementstmt = prepareStatement(handler, ms.getStatementLog());// 执行查询return handler.query(stmt, resultHandler);} finally {// 关闭 StatementcloseStatement(stmt);}
}// 准备 Statement
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {Statement stmt;// 获取数据库连接Connection connection = getConnection(statementLog);// 准备 Statementstmt = 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:// 对于预编译语句,使用 PreparedStatementHandlerdelegate = 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 {// 实例化 Statementstatement = instantiateStatement(connection);// 设置超时时间setStatementTimeout(statement, transactionTimeout);// 设置 fetchSizesetFetchSize(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 {// 转换为 PreparedStatementPreparedStatement ps = (PreparedStatement) statement;// 执行 SQLps.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;// 如果没有找到任何值且需要非空结果,则返回 nullfoundValues = 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;
}