ResultSetHandler是MyBatis中将JDBC ResultSet映射为Java对象的核心组件,由DefaultResultSetHandler实现,通过handleResultSets→handleResultSet→handleRowValues→getRowValue流程,结合元数据、TypeHandler、反射及嵌套逻辑完成映射。

ResultSetHandler 是 MyBatis 中负责将 JDBC ResultSet 映射为 Java 对象的核心组件,其核心逻辑封装在 DefaultResultSetHandler 类中。它不直接解析 SQL 或执行查询,而是在 StatementHandler 执行完 executeQuery() 得到 ResultSet 后,承担“结果翻译”职责。
映射入口:handleResultSets() 方法
对外暴露的主入口是 handleResultSets(Statement stmt) 方法,它支持多结果集(如存储过程返回多个结果),对每个 ResultSet 调用 handleResultSet() 进行处理:
- 先调用
resultSet.getMetaData()获取列元信息(列名、类型、别名等) - 根据
mappedStatement.getResultMap()找到配置的ResultMap - 若未显式配置
resultMap,则按resultType自动生成一个默认ResultMap - 最终委托给
DefaultResultSetHandler.handleRowValues()逐行处理
核心映射流程:handleRowValues() 与 RowBounds
该方法决定是否分页、跳过前 N 行,并控制循环读取 ResultSet.next()。关键步骤包括:
- 检查是否启用自动映射(
autoMapping)和驼峰转换(mapUnderscoreToCamelCase) - 调用
getRowValue(rs, resultMap)处理单行数据 - 对嵌套结果(
<association>/<collection>)会触发嵌套映射逻辑,可能递归调用自身或使用createResultObject()构造子对象 - 支持延迟加载(LazyLoading),此时仅设置代理对象,访问时才触发子查询
对象创建与属性赋值:getRowValue() 的关键细节
这是真正完成“从 ResultSet 到 Object”转换的一环:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- 先调用
createResultObject()创建目标对象实例(通过反射或对象工厂) - 遍历
ResultMap.getResultMappings(),对每个ResultMapping执行:
– 根据column或property匹配字段
– 调用rs.getObject(columnName)获取原始值
– 经过类型处理器(TypeHandler)转换为目标 Java 类型(如String → LocalDateTime)
– 使用反射或元数据设置到对象属性(支持 private 字段 + setter 或字段直写) - 对
id映射的字段,还会参与一级/二级缓存的 key 构建和结果去重(避免同一记录被多次创建)
特殊场景支持:鉴别器(discriminator)、自动映射、嵌套查询
MyBatis 通过扩展机制应对复杂映射需求:
-
discriminator:根据某列值动态选择子
ResultMap,由applyDiscriminator()实现分支判断 -
autoMapping:开启后,未在
resultMap中显式声明的列,只要列名能匹配属性名(经驼峰转换后),就自动赋值 -
嵌套查询(select):遇到
select="xxx"的association或collection,不从当前ResultSet取值,而是提取关联字段(如user_id),组装参数后执行新 SQL 查询 -
嵌套结果(resultMap):复用当前
ResultSet的列前缀(如address.id,address.city),通过列名前缀隔离不同对象字段
理解 ResultSetHandler 的关键在于抓住“元数据驱动 + 类型处理器 + 反射赋值 + 嵌套协调”这一主线。它不是硬编码映射规则,而是把 XML/注解中定义的 ResultMap 结构转化为运行时可执行的映射策略,兼顾灵活性与性能。

















