mybatis 之 SimpleStatementHandler 的 query方法怎么得到映射对象的list集合的

首先,入口类 SimpleStatementHandler

@Override
  public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
    String sql = boundSql.getSql();
    statement.execute(sql);
    return resultSetHandler.<E>handleResultSets(statement);
  }

进入mybatis默认的 DefaultResultSetHandler类 , 

handleResultSets方法 处理结果集的映射:
  @Override
  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();
    int resultMapCount = resultMaps.size();
    validateResultMapsCount(rsw, resultMapCount);
    while (rsw != null && resultMapCount > resultSetCount) {
      ResultMap resultMap = resultMaps.get(resultSetCount);
      handleResultSet(rsw, resultMap, multipleResults, null);
      rsw = getNextResultSet(stmt);
      cleanUpAfterHandlingResultSet();
      resultSetCount++;
    }

其他的不管,重点看 方法  handleResultSet(rsw, resultMap, multipleResults, null);

是怎么把 一个个ResultMap类型的映射对象 转变成 java的具体对象。

具体的java对象是保存在 multipleResults中的,如 debug截图所示:

解析参数:

ResultSetWrapper rsw : 该参数中 包含了 配置在mapper.xml中的某个映射对象(resultMap或resultType)的 几乎所有信息。
class ResultSetWrapper {

  private final ResultSet resultSet;
  private final TypeHandlerRegistry typeHandlerRegistry;
  private final List<String> columnNames = new ArrayList<String>();--列名
  private final List<String> classNames = new ArrayList<String>();--类路径名
  private final List<JdbcType> jdbcTypes = new ArrayList<JdbcType>();--JdbcType类型列表
  private final Map<String, Map<Class<?>, TypeHandler<?>>> typeHandlerMap = new HashMap<String, Map<Class<?>, TypeHandler<?>>>();

debug得到的 ResultSetWrapper rsw 对象的内容如下:

开始重点分析:

类DefaultResultSetHandler的方法handleRowValues中的方法handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);

不考虑嵌套(只考虑单个result模式下,怎么把sql得到的resultType或resultMap对象转化成具体的javaBean对象的,包括javaBean对象的字段,各个方法)。

获取单row的值:

DefaultResultSetHandler 的 getRowValue 方法

DefaultResultSetHandler 的 createResultObject(ResultSetWrapper rsw, ResultMap resultMap, ResultLoaderMap lazyLoader, String columnPrefix) 方法

因为mybatis dao层里面的都是接口,所以此时拿到

final Class<?> resultType = resultMap.getType();

里面返回的javaBean对象,

使用ObjectFactory工厂 以及resultType 里的类路径 创建类的实例。

DefaultObjectFactory

@Override
public <T> T create(Class<T> type) {
  return create(type, null, null);
}

此时创建的resultObject对象是一个 参数皆为空的对象,还需要赋值。

resultObject对象赋值的话,实现的是 接口

TypeHandler的  getResult(ResultSet rs, String columnName) 或 getResult(ResultSet rs, int columnIndex) 方法,

通过 列名或者列索引 查询得到结果集rs中 对应字段的值,赋值到resultObject对象的相应字段。

最后 回到类DefaultResultSetHandler 的

handleRowValuesForSimpleResultMap()方法的 
storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());

保存映射得到的结果对象。

debug下去,把映射的结果集传回来:

closeResultSet(rsw.getResultSet());

关闭该行记录的rsw, 

最终 

return collapseSingleResultList(multipleResults);

类PreparedStatementHandler 的  return resultSetHandler.<E> handleResultSets(ps);

类SimpleExecutor的

return handler.<E>query(stmt, resultHandler);
closeStatement(stmt); 关闭 Statement

回到最外层的实现类 DefaultSqlSession 

的 selectOne(String statement, Object parameter)

返回对象。 结束:

回过头来 看一下最重要的几行代码:

类DefaultResultSetHandler 中的:

private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)
      throws SQLException {
    DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>();
    skipRows(rsw.getResultSet(), rowBounds);
    while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
      ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);
      Object rowValue = getRowValue(rsw, discriminatedResultMap);
      storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
    }
  }
第一步:skipRows(rsw.getResultSet(), rowBounds); 根据rowBounds中的offset值 定位到指定的记录行

第二步: 

while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) { 校验是否还有需要映射的记录

第三步:

ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);

确定映射使用的 resultMap 对象。

最复杂的一步:

Object rowValue = getRowValue(rsw, discriminatedResultMap); 对resultMap中的一行记录进行映射。(分两步:首先创建resultMap对应的 javaBean对象,然后给该javaBean对象的每个字段一一赋值)。
private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException {
    final ResultLoaderMap lazyLoader = new ResultLoaderMap();
    Object resultObject = createResultObject(rsw, resultMap, lazyLoader, null);
    if (resultObject != null && !typeHandlerRegistry.hasTypeHandler(resultMap.getType())) {
      final MetaObject metaObject = configuration.newMetaObject(resultObject);
      boolean foundValues = !resultMap.getConstructorResultMappings().isEmpty();
      if (shouldApplyAutomaticMappings(resultMap, false)) {
        foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, null) || foundValues;
      }
      foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, null) || foundValues;
      foundValues = lazyLoader.size() > 0 || foundValues;
      resultObject = foundValues ? resultObject : null;
      return resultObject;
    }
    return resultObject;
  }
Object resultObject = createResultObject(rsw, resultMap, lazyLoader, null); 创建对象
foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, null) || foundValues; 给创建的对象的每一行 赋值。

猜你喜欢

转载自blog.csdn.net/tuyf_hs/article/details/88174428