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

本文深入解析MyBatis的DefaultResultSetHandler类如何将数据库查询结果映射为Java对象,详细介绍了处理过程中的关键步骤,包括ResultMap的使用、ResultLoaderMap的创建、JavaBean对象的创建及字段赋值过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先,入口类 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; 给创建的对象的每一行 赋值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值