mybatis源码学习------ResultSetHandler之嵌套映射

本文深入剖析了mybatis DefaultResultSetHandler在处理嵌套映射时的逻辑,包括skipRows、shouldProcessMoreRow、resolveDiscriminatedResultMap等步骤,以及createRowKey方法的实现,用于生成CacheKey对象。通过对getRowValue方法的分析,揭示了如何应用nestedResultMappings以解决循环引用问题并映射记录值。
摘要由CSDN通过智能技术生成

DefaultResultSetHandler的handleRowValues方法中有两个分支,一个用于处理嵌套映射,一个用于处理简单映射,本文讲分析其处理嵌套映射的分支。

handleRowValues方法的定义如下:

public void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
   
  if (resultMap.hasNestedResultMaps()) {
   //是否存在嵌套结果映射
    //RowBounds配置校验
    ensureNoRowBounds();
    //ResultHandler校验
    checkResultHandler();
    handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
  } else {
   //简单映射
    handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
  }
}

ensureNoRowBounds

safeRowBoundsEnabled属性的含义为:是否允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为 false。默认值为false

private void ensureNoRowBounds() {
   
  if (configuration.isSafeRowBoundsEnabled() && rowBounds != null && (rowBounds.getLimit() < RowBounds.NO_ROW_LIMIT || rowBounds.getOffset() > RowBounds.NO_ROW_OFFSET)) {
   
    throw new ExecutorException("Mapped Statements with nested result mappings cannot be safely constrained by RowBounds. "
        + "Use safeRowBoundsEnabled=false setting to bypass this check.");
  }
}

checkResultHandler

safeResultHandlerEnabled属性的含义为:是否允许在嵌套语句中使用结果处理器(ResultHandler)。如果允许使用则设置为 false。默认值为true

protected void checkResultHandler() {
   
  if (resultHandler != null && configuration.isSafeResultHandlerEnabled() && !mappedStatement.isResultOrdered()) {
   
    throw new ExecutorException("Mapped Statements with nested result mappings cannot be safely used with a custom ResultHandler. "
        + "Use safeResultHandlerEnabled=false setting to bypass this check "
        + "or ensure your statement returns ordered data and set resultOrdered=true on it.");
  }
}

handleRowValuesForNestedResultMap

处理嵌套映射的代码如下,主要用于解决<resultMap>嵌套<resultMap><resultMap>嵌套<association><resultMap>嵌套<collection>的情况。

private void handleRowValuesForNestedResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
   
  //创建上下文辅助类
  final DefaultResultContext<Object> resultContext = new DefaultResultContext<>();
  //获取结果集
  ResultSet resultSet = rsw.getResultSet();
  //跳过指定记录数
  skipRows(resultSet, rowBounds);
  Object rowValue = previousRowValue;
  //判断能否继续映射结果集中剩余的记录
  while (shouldProcessMoreRows(resultContext, rowBounds) && !resultSet.isClosed() && resultSet.next()) {
   
    //处理鉴别器,确定映射所使用的ResultMap对象
    final ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(resultSet, resultMap, null);
    //为当前记录创建对应的CacheKey对象
    final CacheKey rowKey = createRowKey(discriminatedResultMap, rsw, null);
    //根据上面创建的从嵌套映射关联的结果对象集合中查询
    Object partialObject = nestedResultObjects.get(rowKey);
    if (mappedStatement.isResultOrdered()) {
   //resultOrdered属性为真
      if (partialObject == null && rowValue != null) {
   //partialObject为null表示主结果发生变化
        //释放nestedResultObjects的空间
        nestedResultObjects.clear();
        //保存结果对象
        storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
      }
      //完成对该记录的映射
      rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, null, partialObject);
    } else {
   
      //完成对该记录的映射
      rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, null, partialObject);
      if (partialObject == null) {
   //partialObject为null表示主结果发生变化
        storeObject(r
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值