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.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;
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/931443.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!