前言
MyBatis 是一款广受欢迎的 Java 持久层框架,其中的四大核心组件之一是 ResultSetHandler。
ResultSetHandler 负责处理 JDBC 查询返回的 ResultSet,并将结果映射成 Java 对象。本文将深入解析 ResultSetHandler 的源码,探讨其实现原理、核心方法,以及在 MyBatis 中的作用。
ResultSetHandler 简介与作用
在 MyBatis 中,ResultSetHandler 起到了重要的桥梁作用。当我们执行查询操作时,JDBC 会返回一个 ResultSet 对象,而 ResultSetHandler 就负责将这个 ResultSet 转化为 Java 对象。具体而言,ResultSetHandler 的作用包括:
1.结果集映射: 将 ResultSet 中的数据映射到 Java 对象上,形成查询结果。
2.多结果集处理: 处理存储过程等情况下的多结果集返回。
3.懒加载处理: 处理延迟加载,将查询结果中的延迟加载的部分进行懒加载。
ResultSetHandler 接口
ResultSetHandler 是 MyBatis 中的一个接口,定义了处理结果集的方法。核心方法包括:
handleResultSets(Statement stmt): 处理包含多个 ResultSet 的情况,返回一个包含映射结果的 List。
handleOutputParameters(CallableStatement cs): 处理存储过程等情况下的输出参数。
handleResultSets(Statement stmt, int resultSetType): 处理指定 ResultSet 类型的情况。
handleCursorResultSets(Statement stmt): 处理存储过程等情况下的游标结果集。
DefaultResultSetHandler 类
DefaultResultSetHandler 是 ResultSetHandler 接口的默认实现类,负责处理结果集映射的具体逻辑。以下是 DefaultResultSetHandler 中的核心方法:
handleResultSets
该方法负责处理多个 ResultSet 的情况,将每个 ResultSet 映射成 Java 对象,并最终返回映射结果的列表。
@Override public List<Object> handleResultSets(Statement stmt) throws SQLException { ErrorContext.instance().activity("handling results").object(mappedStatement.getId()); // 处理多个 ResultSet 的情况 List<Object> multipleResults = new ArrayList<>(); int resultSetCount = 0; ResultSetWrapper rsw = getFirstResultSet(stmt); // 遍历结果集 while (rsw != null && !rsw.isClosed() && rsw.getResultSet().getStatement().getMoreResults()) { handleResultSet(rsw, multipleResults, resultSetCount); rsw = getNextResultSet(stmt); cleanUpAfterHandlingResultSet(); resultSetCount++; } // 处理多结果集时的映射逻辑 return collapseSingleResultList(multipleResults); }
handleResultSet
该方法用于处理单个 ResultSet 的映射逻辑,包括处理简单的映射关系和嵌套结果集。在处理单个 ResultSet 时,调用 handleRowValues 方法进行映射。
private void handleResultSet(ResultSetWrapper rsw, List<Object> multipleResults, int resultSetCount) throws SQLException { List<ResultMap> resultMaps = mappedStatement.getResultMaps(); ResultMap resultMap = resultMaps.get(resultSetCount); // 处理单个 ResultSet 的映射逻辑 handleRowValues(rsw, resultMap, multipleResults, null); // 处理嵌套结果集 if (resultMap.hasNestedResultMaps()) { handleRowValuesForNestedResultMap(rsw, resultMap, multipleResults, null); } }
handleRowValues
该方法用于处理单行记录的映射关系,根据是否存在嵌套结果集分别调用
handleRowValuesForSimpleResultMap 或 handleRowValuesForNestedResultMap 方法。
private void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException { if (resultMap.hasNestedResultMaps()) { ensureNoRowWithNestedResultMap(rsw, resultMap); } else { // 处理简单的映射关系 handleRowValuesForSimpleResultMap(rsw, resultMap, multipleResults, parentMapping); } }
结语
通过深度解析 ResultSetHandler 的源码,我们更清晰地了解了其在 MyBatis 中的核心作用。ResultSetHandler 不仅完成了结果集到 Java 对象的映射,还处理了多结果集、嵌套结果集等复杂场景。熟悉 ResultSetHandler 的源码实现,有助于我们更好地理解 MyBatis 的内部机制,提高对查询操作的灵活应用。
开源项目
- SpringCloud + Vue3 微服务商城
Github | Gitee | |
后端 | youlai-mall🍃 | youlai-mall🍃 |
前端 | mall-admin🌺 | mall-admin🌺 |
移动端 | mall-app🍌 | mall-app🍌 |
SpringBoot 3+ Vue3 单体权限管理系统
Github | Gitee | |
后端 | youlai-boot🍃 | youlai-boot🍃 |
前端 | vue3-element-admin🌺 | vue3-element-admin🌺 |