SqlSession 的四大对象是指:Executor, StatementHandler,ParameterHandler,ResultHandler对象。Mybatis通过四大对象的相互协作,完成对数据库的操作。

这篇我们讲解最后的两个对象 ParameterHandler 和 ResultHandler。

1. ParameterHandler

上篇mybatis学习_SqlSession的四大对象(2)说到,在StatmentHandler中,使用了ParameterHandler帮助其完成对预编译参数的设置。

先来看看Paramrterhandler的接口定义

public interface ParameterHandler {

  Object getParameterObject();

  void setParameters(PreparedStatement ps)
      throws SQLException;

}

非常的简洁,就两个方法,一个用来获取参数对象,一个用来设置参数。

我们重点看看设置参数方法setParameters在 其唯一的实现类 DefaultParameterHandler中的实现

public void setParameters(PreparedStatement ps) {
    ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
    if (parameterMappings != null) {
      //遍历了所有的需要设置的预编译参数。对应着xml文件中的#{}表达式
      //这里仅仅只注入#{}中的参数,${}表达式代表的不是预编译参数,所以不在这里注入
      for (int i = 0; i < parameterMappings.size(); i++) {
        ParameterMapping parameterMapping = parameterMappings.get(i);
        if (parameterMapping.getMode() != ParameterMode.OUT) {
          //获取到预编译参数对应的参数值:value
          Object value;
          String propertyName = parameterMapping.getProperty();
          if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
            value = boundSql.getAdditionalParameter(propertyName);
          } else if (parameterObject == null) {
            value = null;
          } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
            value = parameterObject;
          } else {
            MetaObject metaObject = configuration.newMetaObject(parameterObject);
            value = metaObject.getValue(propertyName);
          }
          TypeHandler typeHandler = parameterMapping.getTypeHandler();
          JdbcType jdbcType = parameterMapping.getJdbcType();
          if (value == null && jdbcType == null) {
            jdbcType = configuration.getJdbcTypeForNull();
          }
          try {
            //由typeHandler完成参数的设置
            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);
          }
        }
      }
    }
  }

梳理一下。在这个方法中会遍历所有#{}表达式所表示的预编译参数,并尝试从参数对象中获取参数对应的值。最后把这个值交给TypeHandler去注入。TypeHandler完成对jdbcType和javaType的映射后,调用parameterStatement对应的 setXXX(value)方法完成参数的设置。

 

2. ResultSetHandler

ResultSetHandler 的作用就是将 Statement执行返回的 resultSet映射成对应的类型。

public List<Object> handleResultSets(Statement stmt) throws SQLException {
    ErrorContext.instance().activity("handling results").object(mappedStatement.getId());

    final List<Object> multipleResults = new ArrayList<Object>();

    int resultSetCount = 0;
    //获取结果集的第一个结果
    ResultSetWrapper rsw = getFirstResultSet(stmt);

    List<ResultMap> resultMaps = mappedStatement.getResultMaps();
    //获取resultMap的长度,我们写的resultTye和resulrMap都会被封装成resultMap
    //这个长度通常为1
    int resultMapCount = resultMaps.size();
    validateResultMapsCount(rsw, resultMapCount);
    while (rsw != null && resultMapCount > resultSetCount) {
      ResultMap resultMap = resultMaps.get(resultSetCount);
      //这里把结果转换成java对象
      handleResultSet(rsw, resultMap, multipleResults, null);
      rsw = getNextResultSet(stmt);
      cleanUpAfterHandlingResultSet();
      resultSetCount++;
    }
    //这里处理多结果集
    String[] resultSets = mappedStatement.getResultSets();
    if (resultSets != null) {
      while (rsw != null && resultSetCount < resultSets.length) {
        ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]);
        if (parentMapping != null) {
          String nestedResultMapId = parentMapping.getNestedResultMapId();
          ResultMap resultMap = configuration.getResultMap(nestedResultMapId);
          handleResultSet(rsw, resultMap, null, parentMapping);
        }
        rsw = getNextResultSet(stmt);
        cleanUpAfterHandlingResultSet();
        resultSetCount++;
      }
    }

关于结果集具体的封装细节这里就不具体说了。

那么SqlSession的四大对象的功能,到这里就讲解结束了。SqlSession四大对象是mybatis插件的基础。有关于mybatis插件的讲解,会在后面更新。

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐