MyBatis 源码分析 - 映射文件解析过程 (9)

上面的方法主要用于处理 resultMap 节点的 extend 属性,extend 不为空的话,这里将当前 resultMappings 集合和扩展 resultMappings 集合合二为一。随后,通过建造模式构建 ResultMap 实例。过程如下:

// -☆- ResultMap public ResultMap build() { if (resultMap.id == null) { throw new IllegalArgumentException("ResultMaps must have an id"); } resultMap.mappedColumns = new HashSet<String>(); resultMap.mappedProperties = new HashSet<String>(); resultMap.idResultMappings = new ArrayList<ResultMapping>(); resultMap.constructorResultMappings = new ArrayList<ResultMapping>(); resultMap.propertyResultMappings = new ArrayList<ResultMapping>(); final List<String> constructorArgNames = new ArrayList<String>(); for (ResultMapping resultMapping : resultMap.resultMappings) { /* * 检测 <association> 或 <collection> 节点 * 是否包含 select 和 resultMap 属性 */ resultMap.hasNestedQueries = resultMap.hasNestedQueries || resultMapping.getNestedQueryId() != null; resultMap.hasNestedResultMaps = resultMap.hasNestedResultMaps || (resultMapping.getNestedResultMapId() != null && resultMapping.getResultSet() == null); final String column = resultMapping.getColumn(); if (column != null) { // 将 colum 转换成大写,并添加到 mappedColumns 集合中 resultMap.mappedColumns.add(column.toUpperCase(Locale.ENGLISH)); } else if (resultMapping.isCompositeResult()) { for (ResultMapping compositeResultMapping : resultMapping.getComposites()) { final String compositeColumn = compositeResultMapping.getColumn(); if (compositeColumn != null) { resultMap.mappedColumns.add(compositeColumn.toUpperCase(Locale.ENGLISH)); } } } // 添加属性 property 到 mappedProperties 集合中 final String property = resultMapping.getProperty(); if (property != null) { resultMap.mappedProperties.add(property); } // 检测当前 resultMapping 是否包含 CONSTRUCTOR 标志 if (resultMapping.getFlags().contains(ResultFlag.CONSTRUCTOR)) { // 添加 resultMapping 到 constructorResultMappings 中 resultMap.constructorResultMappings.add(resultMapping); // 添加属性(constructor 节点的 name 属性)到 constructorArgNames 中 if (resultMapping.getProperty() != null) { constructorArgNames.add(resultMapping.getProperty()); } } else { // 添加 resultMapping 到 propertyResultMappings 中 resultMap.propertyResultMappings.add(resultMapping); } if (resultMapping.getFlags().contains(ResultFlag.ID)) { // 添加 resultMapping 到 idResultMappings 中 resultMap.idResultMappings.add(resultMapping); } } if (resultMap.idResultMappings.isEmpty()) { resultMap.idResultMappings.addAll(resultMap.resultMappings); } if (!constructorArgNames.isEmpty()) { // 获取构造方法参数列表,篇幅原因,这个方法不分析了 final List<String> actualArgNames = argNamesOfMatchingConstructor(constructorArgNames); if (actualArgNames == null) { throw new BuilderException("Error in result map '" + resultMap.id + "'. Failed to find a constructor in '" + resultMap.getType().getName() + "' by arg names " + constructorArgNames + ". There might be more info in debug log."); } // 对 constructorResultMappings 按照构造方法参数列表的顺序进行排序 Collections.sort(resultMap.constructorResultMappings, new Comparator<ResultMapping>() { @Override public int compare(ResultMapping o1, ResultMapping o2) { int paramIdx1 = actualArgNames.indexOf(o1.getProperty()); int paramIdx2 = actualArgNames.indexOf(o2.getProperty()); return paramIdx1 - paramIdx2; } }); } // 将以下这些集合变为不可修改集合 resultMap.resultMappings = Collections.unmodifiableList(resultMap.resultMappings); resultMap.idResultMappings = Collections.unmodifiableList(resultMap.idResultMappings); resultMap.constructorResultMappings = Collections.unmodifiableList(resultMap.constructorResultMappings); resultMap.propertyResultMappings = Collections.unmodifiableList(resultMap.propertyResultMappings); resultMap.mappedColumns = Collections.unmodifiableSet(resultMap.mappedColumns); return resultMap; }

以上代码看起来很复杂,实际上这是假象。以上代码主要做的事情就是将 ResultMapping 实例及属性分别存储到不同的集合中,仅此而已。ResultMap 中定义了五种不同的集合,下面分别介绍一下这几种集合。

集合名称 用途
mappedColumns   用于存储 <id>、<result>、<idArg>、<arg> 节点 column 属性  
mappedProperties   用于存储 <id> 和 <result> 节点的 property 属性,或 <idArgs> 和 <arg> 节点的 name 属性  
idResultMappings   用于存储 <id> 和 <idArg> 节点对应的 ResultMapping 对象  
propertyResultMappings   用于存储 <id> 和 <result> 节点对应的 ResultMapping 对象  
constructorResultMappings   用于存储 <idArgs> 和 <arg> 节点对应的 ResultMapping 对象  

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpszjz.html