相关推荐recommended
MyBatis 四大核心组件之 ResultSetHandler 源码解析
作者:mmseoamin日期:2023-12-14

🚀 作者主页: 有来技术

🔥 开源项目: youlai-mall 🍃 vue3-element-admin 🍃 youlai-boot

🌺 仓库主页: Gitee 💫 Github 💫 GitCode

💖 欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请纠正!

MyBatis 四大核心组件之 ResultSetHandler 源码解析,第1张

目录

  • 前言
  • ResultSetHandler 简介与作用
  • ResultSetHandler 接口
  • DefaultResultSetHandler 类
    • handleResultSets
    • handleResultSet
    • handleRowValues
    • 结语
    • 开源项目

      前言

      MyBatis 是一款广受欢迎的 Java 持久层框架,其中的四大核心组件之一是 ResultSetHandler。ResultSetHandler 负责处理 JDBC 查询返回的 ResultSet,并将结果映射成 Java 对象。本文将深入解析 ResultSetHandler 的源码,探讨其实现原理、核心方法,以及在 MyBatis 中的作用。

      ResultSetHandler 简介与作用

      在 MyBatis 中,ResultSetHandler 起到了重要的桥梁作用。当我们执行查询操作时,JDBC 会返回一个 ResultSet 对象,而 ResultSetHandler 就负责将这个 ResultSet 转化为 Java 对象。具体而言,ResultSetHandler 的作用包括:

      1. 结果集映射: 将 ResultSet 中的数据映射到 Java 对象上,形成查询结果。
      2. 多结果集处理: 处理存储过程等情况下的多结果集返回。
      3. 懒加载处理: 处理延迟加载,将查询结果中的延迟加载的部分进行懒加载。

      ResultSetHandler 接口

      MyBatis 四大核心组件之 ResultSetHandler 源码解析,在这里插入图片描述,第2张

      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 handleResultSets(Statement stmt) throws SQLException {
            ErrorContext.instance().activity("handling results").object(mappedStatement.getId());
            // 处理多个 ResultSet 的情况
            List 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 multipleResults, int resultSetCount) throws SQLException {
            List 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 multipleResults, ResultMapping parentMapping) throws SQLException {
            if (resultMap.hasNestedResultMaps()) {
                ensureNoRowWithNestedResultMap(rsw, resultMap);
            } else {
                // 处理简单的映射关系
                handleRowValuesForSimpleResultMap(rsw, resultMap, multipleResults, parentMapping);
            }
        }
         
        

        结语

        通过深度解析 ResultSetHandler 的源码,我们更清晰地了解了其在 MyBatis 中的核心作用。ResultSetHandler 不仅完成了结果集到 Java 对象的映射,还处理了多结果集、嵌套结果集等复杂场景。熟悉 ResultSetHandler 的源码实现,有助于我们更好地理解 MyBatis 的内部机制,提高对查询操作的灵活应用。

        开源项目