本篇对mybatis从取到数据库数据开始到映射成对象并返回的过程进行了详细的分析。
- 转换ResultSet成java对象
- 新建对象并赋值
- 通过mapping映射属性
- 获取Mapping
- 总结
下面的代码是PreparedStatementHandler中的
@Override
public Cursor queryCursor(Statement statement) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
//这里是执行sql并得到ResultSet
ps.execute();
//这里是真正处理ResultSet,将之转换成java对象的地方
return resultSetHandler. handleCursorResultSets(ps);
}
//resultSetHandler是DefaultResultSetHandler类型的
@Override
public List
private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException {
final ResultLoaderMap lazyLoader = new ResultLoaderMap();
//创建一个对象来接受数据(根据配置生成相应的对象)
Object rowValue = createResultObject(rsw, resultMap, lazyLoader, null);
if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
final MetaObject metaObject = configuration.newMetaObject(rowValue);
boolean foundValues = this.useConstructorMappings;
//看是否需要自动映射
if (shouldApplyAutomaticMappings(resultMap, false)) {
//自动映射,把结果放到metaObject的originalObject也就是rowValue中(具体函数看下方)
foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, null) || foundValues;
}
//通过属性映射来找
foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, null) || foundValues;
foundValues = lazyLoader.size() > 0 || foundValues;
//看这段貌似可以在configuration中设置若找不到就实例化一个初始的对象
rowValue = (foundValues || configuration.isReturnInstanceForEmptyRow()) ? rowValue : null;
}
//返回解析好的行值
return rowValue;
}
private boolean applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {
//这个是自动获取mapping,也是比较重要的函数(下方有具体的分析)
List autoMapping = createAutomaticMappings(rsw, resultMap, metaObject, columnPrefix);
boolean foundValues = false;
if (autoMapping.size() > 0) {
for (UnMappedColumnAutoMapping mapping : autoMapping) {
//遍历autoMapping
//从resultSet中解析出值
//解析的方法很简单,就不跟了,大概就是调用typeHandler中的get函数,取出和列名相对应的值就行了
final Object value = mapping.typeHandler.getResult(rsw.getResultSet(), mapping.column);
if (value != null) {
//value不为空说明找到了
foundValues = true;
}
if (value != null || (configuration.isCallSettersOnNulls() && !mapping.primitive)) {
// gcode issue #377, call setter on nulls (value is not 'found')
//找到了就把值设置到 metaObject中的objectWrapper中的object中。其实就是metaObject中的originalObject
metaObject.setValue(mapping.property, value);
}
}
}
//返回是否找到
return foundValues;
}
//创建自动映射的mapping
private List createAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {
final String mapKey = resultMap.getId() + ":" + columnPrefix;
看缓存里有没有
List autoMapping = autoMappingsCache.get(mapKey);
//没有就自己造
if (autoMapping == null) {
//存放映射的UnMappedColumnAutoMapping(一个对应一个字段映射)
autoMapping = new ArrayList();
//通过resultSetWrapper来创建未映射的字段的映射(具体方法看下面)
final List unmappedColumnNames = rsw.getUnmappedColumnNames(resultMap, columnPrefix);
for (String columnName : unmappedColumnNames) {
//轮询unmappedColumnNames
String propertyName = columnName;
if (columnPrefix != null && !columnPrefix.isEmpty()) {
// When columnPrefix is specified,
// ignore columns without the prefix.
if (columnName.toUpperCase(Locale.ENGLISH).startsWith(columnPrefix)) {
propertyName = columnName.substring(columnPrefix.length());
} else {
continue;
}
}
//通过metaObject找到属性
final String property = metaObject.findProperty(propertyName, configuration.isMapUnderscoreToCamelCase());
//如果属性不为空且有Set方法的话进入方法
if (property != null && metaObject.hasSetter(property)) {
//查看该字段set的是什么类型
final Class> propertyType = metaObject.getSetterType(property);
//看typeHandlerRegistry有没有处理这种类型的handle,有的话继续
if (typeHandlerRegistry.hasTypeHandler(propertyType, rsw.getJdbcType(columnName))) {
//获取TypeHandler
final TypeHandler> typeHandler = rsw.getTypeHandler(propertyType, columnName);
//生成UnMappedColumnAutoMapping放到autoMapping里
autoMapping.add(new UnMappedColumnAutoMapping(columnName, property, typeHandler, propertyType.isPrimitive()));
} else {
configuration.getAutoMappingUnknownColumnBehavior()
.doAction(mappedStatement, columnName, property, propertyType);
}
} else{
configuration.getAutoMappingUnknownColumnBehavior()
.doAction(mappedStatement, columnName, (property != null) ? property : propertyName, null);
}
}
放到cache中
autoMappingsCache.put(mapKey, autoMapping);
}
//返回autoMapping(回到applyAutomaticMappings方法)
return autoMapping;
}
//ResultSetWrapper类中
public List<String> getUnmappedColumnNames(ResultMap resultMap, String columnPrefix) throws SQLException {
//看缓存有没有,没有自己造,有就直接返回
List<String> unMappedColumnNames = unMappedColumnNamesMap.get(getMapKey(resultMap, columnPrefix));
if (unMappedColumnNames == null) {
//加载映射和没映射字段
loadMappedAndUnmappedColumnNames(resultMap, columnPrefix);
unMappedColumnNames = unMappedColumnNamesMap.get(getMapKey(resultMap, columnPrefix));
}
return unMappedColumnNames;
}
private void loadMappedAndUnmappedColumnNames(ResultMap resultMap, String columnPrefix) throws SQLException {
List<String> mappedColumnNames = new ArrayList<String>();
List<String> unmappedColumnNames = new ArrayList<String>();
final String upperColumnPrefix = columnPrefix == null ? null : columnPrefix.toUpperCase(Locale.ENGLISH);
//获取已经映射过的column
final Set<String> mappedColumns = prependPrefixes(resultMap.getMappedColumns(), upperColumnPrefix);
//轮询里面ResultSetWrapper中的columnNames
for (String columnName : columnNames) {
//转成大写比对
final String upperColumnName = columnName.toUpperCase(Locale.ENGLISH);
//若mappedColumns中有此column
if (mappedColumns.contains(upperColumnName)) {
//加入到mappedColumnNames
mappedColumnNames.add(upperColumnName);
} else {
//否则放入unmappedColumnNames
unmappedColumnNames.add(columnName);
}
}
//最后将mappedColumnNames放到mappedColumnNamesMap
mappedColumnNamesMap.put(getMapKey(resultMap, columnPrefix), mappedColumnNames);
//最后将unmappedColumnNames放到unMappedColumnNamesMap
unMappedColumnNamesMap.put(getMapKey(resultMap, columnPrefix), unmappedColumnNames);
}
其实就几个重要的点。
1.创建对象
2.获得resultHandle
3.获得mapping
4.获得typeHandle
5.通过handle和mapping给对象赋值,然后把对象存到resultHandle中
6.最后返回