Mybatis数据封装过程原理解析

mybatis封装数据过程:mybatis中大量使用了装饰设计模式。
1、最简单的一种情况:xml中没有配置resultMap也就是查询出来直接封装到javabean中。
mybatis源码:
DefaultResultSetHandler.class
//从resultSet的包装类ResultSetWrapper中查询出sql中写的所有column.
final List<String> 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其中ResultMap中的每一个result对应ResultMapping.
public class ResultMap {
private String id;
private Class<?> type;
private List<ResultMapping> resultMappings;
private List<ResultMapping> idResultMappings;
private List<ResultMapping> constructorResultMappings;
private List<ResultMapping> propertyResultMappings;
private Set<String> mappedColumns;
private Discriminator discriminator;
private boolean hasNestedResultMaps; //是否有嵌套标签
private boolean hasNestedQueries;
private Boolean autoMapping;
resultMap对应<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<String> notNullColumns;
private String columnPrefix;
private List<ResultFlag> flags;
private List<ResultMapping> composites;
private String resultSet;
private String foreignColumn;
private boolean lazy;
ResultMapping 对应<ResultMap>标签下的<result标签><collection标签等>

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值