mybatis源码学习------resultMap和sql片段的解析

resultMap的解析

书接上回,mybatis对于<resultMap></resultMap>标签解析的方法入口为:

在这里插入图片描述

resultMapElements(List list)

根据mybatis-3-mapper.dtd文件中对于resultMap的定义可知,一个mapper节点内可以定义任意多个resultMap节点,所以resultMapElements方法会遍历所有的resultMap进行解析,代码如下:

private void resultMapElements(List<XNode> list) {
   
  for (XNode resultMapNode : list) {
   
    try {
   
      resultMapElement(resultMapNode);
    } catch (IncompleteElementException e) {
   
      // ignore, it will be retried
    }
  }
}

resultMapElement(XNode)

调用重载方法,三个参数的resultMapElement方法主要用于后续递归调用,所以这里单参数的resultMapElement方法更像是一个“桥接”方法。

private ResultMap resultMapElement(XNode resultMapNode) {
   
  return resultMapElement(resultMapNode, Collections.emptyList(), null);
}

resultMapElement(XNod, List, Class)方法

resultMapElement方法会为<resultMap></resultMap>中配置的每一个或标签都创建一个ResultMapping对象,并将其保存在一个集合中,最后传递给ResultMapResolver对象进行解析。

private ResultMap resultMapElement(XNode resultMapNode, List<ResultMapping> additionalResultMappings, Class<?> enclosingType) {
   
  ErrorContext.instance().activity("processing " + resultMapNode.getValueBasedIdentifier());
  //因为<resultMap/>标签的配置存在嵌套的情况,所以在代码处理嵌套情况的时候一定会使用递归,
  //这里获取默认值的逻辑主要是为了处理<resultMap/>嵌套<resultMap/>的情况
  String type = resultMapNode.getStringAttribute("type",
    resultMapNode.getStringAttribute("ofType",
      resultMapNode.getStringAttribute("resultType",
        resultMapNode.getStringAttribute("javaType"))));
  //解析type属性所配置的类
  Class<?> typeClass = resolveClass(type);
  if (typeClass == null) {
   
    typeClass = inheritEnclosingType(resultMapNode, enclosingType);
  }
  Discriminator discriminator = null;  //resultMappings集合中维护了当前<resultMap/>中所有的映射关系
  List<ResultMapping> resultMappings = new ArrayList<>(additionalResultMappings);
  List<XNode> resultChildren = resultMapNode.getChildren();
  for (XNode resultChild : resultChildren) {
   
    if ("constructor".equals(resultChild.getName())) {
   //处理构造器
      processConstructorElement(resultChild, typeClass, resultMappings);
    } else if ("discriminator".equals(resultChild.getName())) {
   //处理鉴别器
      discriminator = processDiscriminatorElement(resultChild, typeClass, resultMappings);
    } else {
   //处理其他情况
      List<ResultFlag> flags = new ArrayList<>();
      if ("id".equals(resultChild.getName())) {
   
        flags.add(ResultFlag.ID);
      }
      resultMappings.add(buildResultMappingFromContext(resultChild, typeClass, flags));
    }
  }
  //获取resultMap节点配置的ID
  //getValueBasedIdentifier()方法返回的格式为    类型1[ID1]_类型2[ID2]......
  String id = resultMapNode.getStringAttribute("id",
    resultMapNode.getValueBasedIdentifier());
  //获取resultMap节点配置的继承关系
  String extend = resultMapNode.getStringAttribute("extends");
  //获取是否开启自动映射配置
  Boolean autoMapping = resultMapNode.getBooleanAttribute("autoMapping");
  //创建ResultMap解析器实例
  ResultMapResolver resultMapResolver = new ResultMapResolver(builderAssistant, id, typeClass, extend, discriminator, resultMappings, autoMapping);
  try {
   
    //将具体的解析任务委派给MapperBuilderAssistant的实例
    return resultMapResolver.resolve();
  } catch (IncompleteElementException e) {
   
    configuration.addIncompleteResultMap(resultMapResolver);
    throw e;
  }
}

解析<constructor/>

processConstructorElement方法对构造函数节点中的ID进行了特殊的标识,便于在后续的解析中区分对id和idArg进行区分,如下图所示,:

在这里插入图片描述

private void processConstructorElement(XNode resultChild, Class<?> resultType, List<ResultMapping> resultMappings) {
   
  List
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值