Mybatis是一个半自动化ORM框架,可以将数据库中的记录转换为java实体对象,但是java实体属性通常采用驼峰命名法,而数据库字段习惯采用下划线分隔命名法,因此需要用户指定java实体属性与数据库表字段之间的映射关系。 mybatis的Mapper 配置中提供了resultMap 标签,用于建立数据库字段与java实体属性之间的映射关系。例如:
Mybatis 在启动时,所有配置信息都会被转换为java对象,Mybatis 通过ResultMap类描述resultMap标签的配置信息;在XMLMapperBuilder类的configurationElement()方法中,调用resultMapElements()方法对所有resultMap标签进行解析。resultMapElements()方法最终会调用重载的resultMapElement()方法对每个resultMap标签进行解析。代码如下:
对resultMap标签解析完成后,在StatementHandler组件与数据库完成交互后,需要根据resultMap标签的配置把结果转换为Resultmap对象,就会使用ResultSetHandler组件对结果集进行处理。
在PreparedStatementHandler.query方法中,调用PreparedStatement.execute() 方法完成与数据库交互之后,会调用resultSetHandler.handleResultSets()方法对结果集进行处理。代码如下:
DefaultResultSetHandler类是ResultSetHandler接口的唯一默认实现,DefaultResultSetHandler.handleResultSets()方法中,简化了对JDBC中ResultSet对象的操作,将ResultSet对象包装成ResultSetWrapper对象,然后获取MappedStatement对象对应的ResultMap对象,然后再调用重载的HandleResultSet()方法进行处理,代码如下:
在重载的handleResultSet()方法中做了些逻辑判断,最终都会调用handleRowValues()方法进行处理,代码如下:
handleRowValues()方法中判断ResultMap中是否有嵌套的ResultMap,当使用association或collection标签通过JOIN查询方式进行级联映射时 ,HasNestedResultMaps()方法返回true;如果有嵌套的RresultMap,则调用handleRowValuesForNestedResultMap()方法进行处理,否则调用handleRowValuesForSimpleResultMap()方法,代码如下:
handleRowValuesForSimpleResultMap()方法不含嵌套映射的简单映射的处理。
handleRowValuesForNestedResultMap ()方法是对嵌套映射结果进行处理,在处理过程中,对结果集对象进行遍历,处理每一行数据,首先调用resolveDiscriminatedResultMap()方法处理resultmap标签中通过discriminator标签配置的鉴别器信息,根据字段值获取对应的ResultMap对象,然后调用getRowValue() 方法将结果集中的一行数据转换为java实体对象。
简单映射结果和嵌套映射结果调用了getRowValue() 方法将结果集中的一行数据转换为java实体对象。代码如下:
针对多结果集处理,在getRowValue()方法中调用 applyPropertyMappings()方法映射ResultMap中明确指定的字段。代码如下:
applyPropertyMappings()会调用getPropertyMappingValue()方法完成映射操作,代码如下:
getPropertyMappingValue()会调用addPendingChildRelation()对多结果集的情况进行处理,处理代码如下: