2019独角兽企业重金招聘Python工程师标准>>>

前一章节已经介绍了,把方法分解成什么样子来分析,这里先来分析一个方法resultMapElements,在这个方法前还有cacheRefElement与cacheElement,但是由于配置文件中没有配置这2项,所以这里就先跳过。而parameterMapElement在最新的MyBatis中是过时的,也先跳过,以后可以在补充。

1 配置文件

<resultMap id="BaseResultMap" type="cn.vansky.schedule.time.menu.bo.Menu"><!--WARNING - @mbggeneratedThis element is automatically generated by MyBatis Generator, do not modify.This element was generated on Fri Aug 14 16:08:36 CST 2015.--><id column="Id" property="id" jdbcType="INTEGER" /><result column="menu_name" property="menuName" jdbcType="VARCHAR" /><result column="menu_remark" property="menuRemark" jdbcType="VARCHAR" /><result column="menu_parent_id" property="menuParentId" jdbcType="INTEGER" /><result column="menu_url" property="menuUrl" jdbcType="VARCHAR" /><result column="is_show" property="isShow" jdbcType="TINYINT" /><result column="is_delete" property="isDelete" jdbcType="TINYINT" /><result column="operation_user_name" property="operationUserName" jdbcType="VARCHAR" /><result column="operation_time" property="operationTime" jdbcType="TIMESTAMP" /></resultMap>

这里是使用自己扩展MyBatis的自动生成代码,生成的resultMap配置。

2 代码

private void resultMapElements(List<XNode> list) throws Exception {for (XNode resultMapNode : list) {try {resultMapElement(resultMapNode);} catch (IncompleteElementException e) {// ignore, it will be retried}}}private ResultMap resultMapElement(XNode resultMapNode) throws Exception {return resultMapElement(resultMapNode, Collections.<ResultMapping> emptyList());
}

这里是获取当前文件中所有resultMap对应的XML,然后分别对每个resultMap进行处理。这里会去捕获一个专门的异常,目前还不清楚是起什么作用,先继续往下分析。
3 方法resultMapElement

// resultMapNode是对应的resuleMap的XML信息,这里首先获取配置中的id,如果没有就自动生成一个id
// BaseResultMap
String id = resultMapNode.getStringAttribute("id", resultMapNode.getValueBasedIdentifier());
// 那么这行很明显是获取type了,如果没有就获取ofType,还没有就获取resultType,还是没有就获取javaType
// cn.vansky.schedule.time.menu.bo.Menu
String type = resultMapNode.getStringAttribute("type",
resultMapNode.getStringAttribute("ofType",
resultMapNode.getStringAttribute("resultType", resultMapNode.getStringAttribute("javaType"))));
// 猜想是获取继承的父类
// null
String extend = resultMapNode.getStringAttribute("extends");
// null
Boolean autoMapping = resultMapNode.getBooleanAttribute("autoMapping");
// 获取type对应的Class
Class<?> typeClass = resolveClass(type);
Discriminator discriminator = null;
List<ResultMapping> resultMappings = new ArrayList<ResultMapping>();
// 这里additionalResultMappings是空列表,而不是null
resultMappings.addAll(additionalResultMappings);
// 获取子节点id及result
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 {// id与result都走这里ArrayList<ResultFlag> flags = new ArrayList<ResultFlag>();if ("id".equals(resultChild.getName())) {flags.add(ResultFlag.ID);}resultMappings.add(buildResultMappingFromContext(resultChild, typeClass, flags));}
}

4 buildResultMappingFromContext

以下都是以ID为例,进行分析。

private ResultMapping buildResultMappingFromContext(XNode context, Class<?> resultType, ArrayList<ResultFlag> flags) throws Exception {// idString property = context.getStringAttribute("property");// IdString column = context.getStringAttribute("column");// nullString javaType = context.getStringAttribute("javaType");// INTEGERString jdbcType = context.getStringAttribute("jdbcType");// nullString nestedSelect = context.getStringAttribute("select");// null String nestedResultMap = context.getStringAttribute("resultMap",processNestedResultMappings(context, Collections.<ResultMapping> emptyList()));// nullString notNullColumn = context.getStringAttribute("notNullColumn");// nullString columnPrefix = context.getStringAttribute("columnPrefix");// nullString typeHandler = context.getStringAttribute("typeHandler");// nullString resulSet = context.getStringAttribute("resultSet");// nullString foreignColumn = context.getStringAttribute("foreignColumn");// falseboolean lazy = "lazy".equals(context.getStringAttribute("fetchType", configuration.isLazyLoadingEnabled() ? "lazy" : "eager"));// nullClass<?> javaTypeClass = resolveClass(javaType);@SuppressWarnings("unchecked")// nullClass<? extends TypeHandler<?>> typeHandlerClass = (Class<? extends TypeHandler<?>>) resolveClass(typeHandler);// 获取到JdbcTypeJdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);// 这里就会构建生成一个ResultMappingreturn builderAssistant.buildResultMapping(resultType, property, column, javaTypeClass, jdbcTypeEnum, nestedSelect, nestedResultMap, notNullColumn, columnPrefix, typeHandlerClass, flags, resulSet, foreignColumn, lazy);
}

5 MapperBuilderAssistant的buildResultMapping方法

public ResultMapping buildResultMapping(Class<?> resultType,String property,String column,Class<?> javaType,JdbcType jdbcType,String nestedSelect,String nestedResultMap,String notNullColumn,String columnPrefix,Class<? extends TypeHandler<?>> typeHandler,List<ResultFlag> flags,String resultSet,String foreignColumn, boolean lazy) {// 这里如果配置中有javaType属性直接返回,否则通过type配置的类及属性获取对应的ClassClass<?> javaTypeClass = resolveResultJavaType(resultType, property, javaType);// 获取类型处理器 nullTypeHandler<?> typeHandlerInstance = resolveTypeHandler(javaTypeClass, typeHandler);// 0List<ResultMapping> composites = parseCompositeColumnName(column);if (composites.size() > 0) column = null;// 初始化一些内部信息ResultMapping.Builder builder = new ResultMapping.Builder(configuration, property, column, javaTypeClass);builder.jdbcType(jdbcType);builder.nestedQueryId(applyCurrentNamespace(nestedSelect, true));builder.nestedResultMapId(applyCurrentNamespace(nestedResultMap, true));builder.resultSet(resultSet);builder.typeHandler(typeHandlerInstance);builder.flags(flags == null ? new ArrayList<ResultFlag>() : flags);builder.composites(composites);builder.notNullColumns(parseMultipleColumnNames(notNullColumn));builder.columnPrefix(columnPrefix);builder.foreignColumn(foreignColumn);builder.lazy(lazy);return builder.build();}

以上生成的ResultMapping的typeHandler还是为null的,因为这里获取的是在配置文件中对应的TypeHandler。那么就看一下builder.build()里面是什么代码。

public ResultMapping build() {// lock down collectionsresultMapping.flags = Collections.unmodifiableList(resultMapping.flags);resultMapping.composites = Collections.unmodifiableList(resultMapping.composites);resolveTypeHandler();validate();return resultMapping;
}

原来这里根据配置信息解析出默认使用的TypeHandler,还对一些ResultMapping的信息做了验证,具体代码,自行研究就可以了。

6 ResultMapping

6.1 属性

ID最后对应的ResultMapping的信息。

/** 全局配置类 */
private Configuration configuration;
/** id */
private String property;
/** Id */
private String column;
/** java.lang.Integer */
private Class<?> javaType;
/** INTEGER */
private JdbcType jdbcType;
/** IntegerTypeHandler  */
private TypeHandler<?> typeHandler;
/** null */
private String nestedResultMapId;
/** null */
private String nestedQueryId;
/** 空列表 */
private Set<String> notNullColumns;
/** null */
private String columnPrefix;
/** ID */
private List<ResultFlag> flags;
/** 空列表 */
private List<ResultMapping> composites;
/** null */
private String resultSet;
/** null */
private String foreignColumn;
/** false */
private boolean lazy;

menu_name最后对应的ResultMapping的信息。

/** 全局配置类 */
private Configuration configuration;
/** menuName */
private String property;
/** menu_name */
private String column;
/** java.lang.String */
private Class<?> javaType;
/** VARCHAR */
private JdbcType jdbcType;
/** StringTypeHandler */
private TypeHandler<?> typeHandler;
/** null */
private String nestedResultMapId;
/** null */
private String nestedQueryId;
/** 空列表 */
private Set<String> notNullColumns;
/** null */
private String columnPrefix;
/** 空列表 */
private List<ResultFlag> flags;
/** 空列表 */
private List<ResultMapping> composites;
/** null */
private String resultSet;
/** null */
private String foreignColumn;
/** false */
private boolean lazy;

MyBatis的地址http://mybatis.github.io/mybatis-3/zh/sqlmap-xml.html#Result_Maps这里有很多例子,喜欢的童鞋可以多去研究一下。

当对id及result都遍历以后,会生成List<ResultMapping>。

ResultMapResolver resultMapResolver = new ResultMapResolver(builderAssistant, id, typeClass, extend, discriminator, resultMappings, autoMapping);try {return resultMapResolver.resolve();} catch (IncompleteElementException  e) {configuration.addIncompleteResultMap(resultMapResolver);throw e;}

如果这里解析失败会抛出前面出现的捕获异常,并把错误的解析放入Configuration(全局配置类)的Collection<ResultMapResolver> incompleteResultMaps = new LinkedList<ResultMapResolver>()。

7 MapperBuilderAssistant的addResultMap方法

public ResultMap addResultMap(String id,Class<?> type,String extend,Discriminator discriminator,List<ResultMapping> resultMappings,Boolean autoMapping) {// 这里把命名空间与id合并// cn.vansky.schedule.time.menu.dao.MenuMapper.BaseResultMapid = applyCurrentNamespace(id, false);// null extend = applyCurrentNamespace(extend, true);ResultMap.Builder resultMapBuilder = new ResultMap.Builder(configuration, id, type, resultMappings, autoMapping);if (extend != null) {if (!configuration.hasResultMap(extend)) {throw new IncompleteElementException("Could not find a parent resultmap with id '" + extend + "'");}ResultMap resultMap = configuration.getResultMap(extend);List<ResultMapping> extendedResultMappings = new ArrayList<ResultMapping>(resultMap.getResultMappings());extendedResultMappings.removeAll(resultMappings);// Remove parent constructor if this resultMap declares a constructor.boolean declaresConstructor = false;for (ResultMapping resultMapping : resultMappings) {if (resultMapping.getFlags().contains(ResultFlag.CONSTRUCTOR)) {declaresConstructor = true;break;}}if (declaresConstructor) {Iterator<ResultMapping> extendedResultMappingsIter = extendedResultMappings.iterator();while (extendedResultMappingsIter.hasNext()) {if (extendedResultMappingsIter.next().getFlags().contains(ResultFlag.CONSTRUCTOR)) {extendedResultMappingsIter.remove();}}}resultMappings.addAll(extendedResultMappings);}resultMapBuilder.discriminator(discriminator);// 这里把新增的ResultMapping做了处理ResultMap resultMap = resultMapBuilder.build();configuration.addResultMap(resultMap);return resultMap;}

这里没有具体介绍,还需要慢慢深究。下面来看最终的ResultMap信息。

8 ResultMap属性

// cn.vansky.schedule.time.menu.dao.MenuMapper.BaseResultMap
private String id;
// cn.vansky.schedule.time.menu.bo.Menu
private Class<?> type;
// 对应配置中的所有结果列,这里9个对象
private List<ResultMapping> resultMappings;
// 对应配置中的id列,这里1个对象
private List<ResultMapping> idResultMappings;
// 对应构造器的列,这里为0个对象
private List<ResultMapping> constructorResultMappings;
// 看代码得出,只要不是构造器列,就属于这里,也就是包括id和result
private List<ResultMapping> propertyResultMappings;
// 对应的配置的列名全部大写,这里使用的set所以也就不是按顺序来排列的了
// MENU_PARENT_ID,MENU_NAME,MENU_URL,OPERATION_TIME,IS_SHOW,OPERATION_USER_NAME,ID,IS_DELETE,MENU_REMARK
private Set<String> mappedColumns;
// null
private Discriminator discriminator;
// false
private boolean hasNestedResultMaps;
// false
private boolean hasNestedQueries;
// null
private Boolean autoMapping;

至此最终的ResultMap信息出来了。

总结:

这里很多东西,作者也是一点一点去研究,而且实际项目中的配置也不是特别的多,所以有些还待完善。

转载于:https://my.oschina.net/u/1269959/blog/522346

MyBatis整合Spring的实现(11)相关推荐

  1. MyBatis整合Spring的实现(2)

    2019独角兽企业重金招聘Python工程师标准>>> 分析 MyBatis整合Spring的实现(1)中代码实现的4.1可以知道,XMLConfigBuilder类读取MyBati ...

  2. MyBatis整合Spring原理分析

    目录 MyBatis整合Spring原理分析 MapperScan的秘密 简单总结 假如不结合Spring框架,我们使用MyBatis时的一个典型使用方式如下: public class UserDa ...

  3. (转)MyBatis框架的学习(六)——MyBatis整合Spring

    http://blog.csdn.net/yerenyuan_pku/article/details/71904315 本文将手把手教你如何使用MyBatis整合Spring,这儿,我本人使用的MyB ...

  4. Mybatis——Mybatis整合Spring详解

    mybatis-spring官网 1. MyBatis整合Spring实现 我们首先实现MyBatis和Spring的整合操作. 1.1 添加相关的依赖 这些是整合的依赖,不包括其他分页插件等依赖. ...

  5. 【Mybatis+spring整合源码探秘】--- mybatis整合spring事务原理

    文章目录 1 mybatis整合spring事务原理 1 mybatis整合spring事务原理 本篇文章不再对源码进行具体的解读了,仅仅做了下面一张图: 该图整理了spring+mybatis整合后 ...

  6. Spring学习笔记:Spring整合Mybatis(mybatis-spring.jar)(二:mybatis整合spring)

    http://blog.csdn.net/qq598535550/article/details/51703190 二.Spring整合mybatis其实是在mybatis的基础上实现Spring框架 ...

  7. MyBatis(五)MyBatis整合Spring原理分析

    前面梳理了下MyBatis在单独使用时的工作流程和关键源码,现在看看MyBatis在和Spring整合的时候是怎么工作的 也先从使用开始 Spring整合MyBatis 1.引入依赖,除了MyBati ...

  8. Mybatis整合spring

    整合思路 1.SqlSessionFactory对象应该放到spring容器中作为单例存在. 2.传统dao的开发方式中,应该从spring容器中获得sqlsession对象. 3.Mapper代理形 ...

  9. mybatis 整合spring之mapperLocations配置的问题

    今天尝试spring整合mybatis时遇到这么一个问题,就是在配置sqlSessionFactory时是否要配置mapperLocations的问题. <bean id="sessi ...

最新文章

  1. 能被计算机硬件理解的语言,(计算机原理综合练习一含答案.doc
  2. 阿里云PolarDB发布重大更新 支持Oracle等数据库一键迁移上云
  3. 打基础一定要吃透这12类 Python 内置函数
  4. 如何优雅地在 Linux 上运行 QQ、微信?
  5. DE19 Introduction to the Laplace Transform
  6. 【渝粤题库】广东开放大学 秘书理论与实务(1) 形成性考核
  7. java实例是什么_java 什么是实例
  8. 哆点Linux客户端上网
  9. 优酷kux文件转码成mp4
  10. linux如何卸载oracle数据库实例,linux下删除oracle数据库实例
  11. STM8S003引脚坑(开发过的人都知道)
  12. mysql lbs_LBS类数据服务对比分析 (一)
  13. 非对称加密与数字证书
  14. 拓维信息鸿蒙服务器,润和软件、常山北明、诚迈科技、拓维信息,谁是华为鸿蒙真龙头?...
  15. 大厂程序员裸辞全职接单一个月,感触颇多!
  16. 别把“IT信息化”不当“超级工程”
  17. 伞源科技Pinpoint和sonarQube对比
  18. Java实现三国曹操华容道的游戏
  19. 单链表实现队列的基本操作(入队,出队)
  20. Leetcode(1110)——删点成林

热门文章

  1. DirectShow程序运行过程简析
  2. 安装cifs 访问windows的共享文件
  3. 代码行数统计工具SourceCounter
  4. 一元多项式计算器_人教版初中数学七年级上册——去括号、去分母解一元一次方程公开课优质课课件教案视频...
  5. vi/vim使用进阶: quickfix
  6. IOS实现打电话后回调
  7. android 打开SD卡文件夹,并获得选中文件的路径怎么实现?
  8. Responsive Web Design
  9. Intermapper系列网络管理工具中文版教程
  10. 888. 公平的糖果棒交换