Mybatis数据封装过程原理解析

mybatis封装数据过程:mybatis中大量使用了装饰设计模式。
1、最简单的一种情况:xml中没有配置resultMap也就是查询出来直接封装到javabean中。
mybatis源码:
DefaultResultSetHandler.class
//从resultSet的包装类ResultSetWrapper中查询出sql中写的所有column.
final List unmappedColumnNames = rsw.getUnmappedColumnNames(resultMap, columnPrefix);
boolean foundValues = false;
for (String columnName : unmappedColumnNames) {
String propertyName = columnName;
if (columnPrefix != null && columnPrefix.length() > 0) {
// When columnPrefix is specified,
// ignore columns without the prefix.
if (columnName.toUpperCase(Locale.ENGLISH).startsWith(columnPrefix)) {
propertyName = columnName.substring(columnPrefix.length());
} else {
continue;
}
}
//从metaObject中查询出Object中是否有该property。metaObject是ObjectWrapper的包装类.ObjectWrapper是Object的包装类
final String property = metaObject.findProperty(propertyName, configuration.isMapUnderscoreToCamelCase());
if (property != null && metaObject.hasSetter(property)) {
//拿到字段类型
final Class propertyType = metaObject.getSetterType(property);
if (typeHandlerRegistry.hasTypeHandler(propertyType)) {
//获取处理字段类型的typeHandler
final TypeHandler typeHandler = rsw.getTypeHandler(propertyType, columnName);
//获取值
final Object value = typeHandler.getResult(rsw.getResultSet(), columnName);
if (value != null || configuration.isCallSettersOnNulls()) { // issue #377, call setter on nulls
if (value != null || !propertyType.isPrimitive()) {
//设置值
metaObject.setValue(property, value);
}
foundValues = true;
}
}
}
}

2、封装collection一对多关系或者一对一关系的原理:
首先项目加载的时候读取xml中的标签封装到ResultMap其中ResultMap中的每一个result对应ResultMapping.
public class ResultMap {
private String id;
private Class type;
private List resultMappings;
private List idResultMappings;
private List constructorResultMappings;
private List propertyResultMappings;
private Set mappedColumns;
private Discriminator discriminator;
private boolean hasNestedResultMaps; //是否有嵌套标签
private boolean hasNestedQueries;
private Boolean autoMapping;
resultMap对应标签


public class ResultMapping {

private Configuration configuration;
private String property;
private String column;
private Class javaType;
private JdbcType jdbcType;
private TypeHandler typeHandler;
private String nestedResultMapId;
private String nestedQueryId;
private Set notNullColumns;
private String columnPrefix;
private List flags;
private List composites;
private String resultSet;
private String foreignColumn;
private boolean lazy;
ResultMapping 对应标签下的

public class DefaultResultSetHandler implements ResultSetHandler这个类是处理结果集映射的类,其中定义了两个Map:
private final Map nestedResultObjects = new HashMap(); 保存实体类对象在一对多关系映射的时候,首先从该Map中取对象,如果有就取出来,如果没有就新建。CacheKey根据主键生成。

private final Map ancestorObjects = new HashMap();保存实体嵌套类的对象,先从该Map中根据CacheKey判断是否有对象,有则取出,没有则新建。CacheKey根据嵌套类的id生成。这也是为什么当配置collection的时候一定要配置id标签,因为封装一对多关系的时候是根据id来判断是否存在同一对象进而封装。

你可能感兴趣的:(mybatis)