MyBatis执行SQL查询,比将结果映射为java对象
mybatis利用jdbc的PreparedStatement查询,是如何知道对查询结果ResultSet rs利用rs.getInt 还是用rs.getDate的呢
先从SQL查询的// RoutingStatementHandler类开始进入
@Override
public <E> List<E> query(Statement statement) throws SQLException {
return delegate.<E>query(statement);
}
然后到
@Override
public <E> List<E> query(Statement statement) throws SQLException {
// 这里就到了熟悉的PreparedStatement了
PreparedStatement ps = (PreparedStatement) statement;
// 执行SQL查询操作
ps.execute();
// 结果交给ResultHandler来处理
return resultSetHandler.<E> handleResultSets(ps);
}
然后进入DefaultResultSetHandler类
public List<Object> handleResultSets(Statement stmt) throws SQLException {
ErrorContext.instance().activity("handling results").object(this.mappedStatement.getId());
List<Object> multipleResults = new ArrayList();
int resultSetCount = 0;
ResultSetWrapper rsw = this.getFirstResultSet(stmt);
List<ResultMap> resultMaps = this.mappedStatement.getResultMaps();
int resultMapCount = resultMaps.size();
this.validateResultMapsCount(rsw, resultMapCount);
while(rsw != null && resultMapCount > resultSetCount) {
ResultMap resultMap = (ResultMap)resultMaps.get(resultSetCount);
this.handleResultSet(rsw, resultMap, multipleResults, (ResultMapping)null);
rsw = this.getNextResultSet(stmt);
this.cleanUpAfterHandlingResultSet();
++resultSetCount;
}
String[] resultSets = this.mappedStatement.getResultSets();
if (resultSets != null) {
while(rsw != null && resultSetCount < resultSets.length) {
ResultMapping parentMapping = (ResultMapping)this.nextResultMaps.get(resultSets[resultSetCount]);
if (parentMapping != null) {
String nestedResultMapId = parentMapping.getNestedResultMapId();
ResultMap resultMap = this.configuration.getResultMap(nestedResultMapId);
this.handleResultSet(rsw, resultMap, (List)null, parentMapping);
}
rsw = this.getNextResultSet(stmt);
this.cleanUpAfterHandlingResultSet();
++resultSetCount;
}
}
return this.collapseSingleResultList(multipleResults);
}
ResultSetWrapper是ResultSet的包装类,调用getFirstResultSet方法获取第一个ResultSet,同时获取数据库的MetaData数据,包括数据表列名、列的类型、类序号等,这些信息都存储在ResultSetWrapper类中了。然后调用handleResultSet方法来来进行结果集的封装。
private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException {
try {
if (parentMapping != null) {
this.handleRowValues(rsw, resultMap, (ResultHandler)null, RowBounds.DEFAULT, parentMapping);
} else if (this.resultHandler == null) {
DefaultResultHandler defaultResultHandler = new DefaultResultHandler(this.objectFactory);
this.handleRowValues(rsw, resultMap, defaultResultHandler, this.rowBounds, (ResultMapping)null);
multipleResults.add(defaultResultHandler.getResultList());
} else {
this.handleRowValues(rsw, resultMap, this.resultHandler, this.rowBounds, (ResultMapping)null);
}
} finally {
this.closeResultSet(rsw.getResultSet());
}
}
这里调用DefaultResultSetHandler类的handleRowValues方法来进行值的设置:
public void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
if (resultMap.hasNestedResultMaps()) {
this.ensureNoRowBounds();
this.checkResultHandler();
this.handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
} else {
this.handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
}
}
然后进入
private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
DefaultResultContext<Object> resultContext = new DefaultResultContext();
this.skipRows(rsw.getResultSet(), rowBounds);
while(this.shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
ResultMap discriminatedResultMap = this.resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, (String)null);
Object rowValue = this.getRowValue(rsw, discriminatedResultMap);
this.storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
}
}
然后进入getRowValue方法:
private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException {
ResultLoaderMap lazyLoader = new ResultLoaderMap();
Object rowValue = this.createResultObject(rsw, resultMap, lazyLoader, (String)null);
if (rowValue != null && !this.hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
MetaObject metaObject = this.configuration.newMetaObject(rowValue);
boolean foundValues = this.useConstructorMappings;
if (this.shouldApplyAutomaticMappings(resultMap, false)) {
foundValues = this.applyAutomaticMappings(rsw, resultMap, metaObject, (String)null) || foundValues;
}
foundValues = this.applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, (String)null) || foundValues;
foundValues = lazyLoader.size() > 0 || foundValues;
rowValue = !foundValues && !this.configuration.isReturnInstanceForEmptyRow() ? null : rowValue;
}
return rowValue;
}
// DefaultResultSetHandler类(把ResultSet中查询结果填充到JavaBean中)
private boolean applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {
List<DefaultResultSetHandler.UnMappedColumnAutoMapping> autoMapping = this.createAutomaticMappings(rsw, resultMap, metaObject, columnPrefix);
boolean foundValues = false;
if (!autoMapping.isEmpty()) {
Iterator var7 = autoMapping.iterator();
while(true) {
DefaultResultSetHandler.UnMappedColumnAutoMapping mapping;
Object value;
do {
if (!var7.hasNext()) {
return foundValues;
}
mapping = (DefaultResultSetHandler.UnMappedColumnAutoMapping)var7.next();
value = mapping.typeHandler.getResult(rsw.getResultSet(), mapping.column);
if (value != null) {
foundValues = true;
}
} while(value == null && (!this.configuration.isCallSettersOnNulls() || mapping.primitive));
metaObject.setValue(mapping.property, value);
}
} else {
return foundValues;
}
}
再返回getRowValue方法中执行applyPropertyMappings
private boolean applyPropertyMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException {
List<String> mappedColumnNames = rsw.getMappedColumnNames(resultMap, columnPrefix);
boolean foundValues = false;
List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();
Iterator var9 = propertyMappings.iterator();
while(true) {
while(true) {
Object value;
String property;
do {
ResultMapping propertyMapping;
String column;
do {
if (!var9.hasNext()) {
return foundValues;
}
propertyMapping = (ResultMapping)var9.next();
column = this.prependPrefix(propertyMapping.getColumn(), columnPrefix);
if (propertyMapping.getNestedResultMapId() != null) {
column = null;
}
} while(!propertyMapping.isCompositeResult() && (column == null || !mappedColumnNames.contains(column.toUpperCase(Locale.ENGLISH))) && propertyMapping.getResultSet() == null);
value = this.getPropertyMappingValue(rsw.getResultSet(), metaObject, propertyMapping, lazyLoader, columnPrefix);
property = propertyMapping.getProperty();
} while(property == null);
if (value == DEFERED) {
foundValues = true;
} else {
if (value != null) {
foundValues = true;
}
if (value != null || this.configuration.isCallSettersOnNulls() && !metaObject.getSetterType(property).isPrimitive()) {
metaObject.setValue(property, value);
}
}
}
}
}
然后进入getPropertyMappingValue
private Object getPropertyMappingValue(ResultSet rs, MetaObject metaResultObject, ResultMapping propertyMapping, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException {
if (propertyMapping.getNestedQueryId() != null) {
return this.getNestedQueryMappingValue(rs, metaResultObject, propertyMapping, lazyLoader, columnPrefix);
} else if (propertyMapping.getResultSet() != null) {
this.addPendingChildRelation(rs, metaResultObject, propertyMapping);
return DEFERED;
} else {
TypeHandler<?> typeHandler = propertyMapping.getTypeHandler();
String column = this.prependPrefix(propertyMapping.getColumn(), columnPrefix);
return typeHandler.getResult(rs, column);
}
}
在上面这个方法中:
TypeHandler<?> typeHandler = propertyMapping.getTypeHandler();
这个会返回具体的typeHandler
然后进入到typeHandler.getResult(rs, column);
public T getResult(ResultSet rs, String columnName) throws SQLException {
Object result;
try {
result = this.getNullableResult(rs, columnName);
} catch (Exception var5) {
throw new ResultMapException("Error attempting to get column '" + columnName + "' from result set. Cause: " + var5, var5);
}
return rs.wasNull() ? null : result;
}
例如typeHandler为LongTypeHandler的话,那么进入到LongTypeHandler的getNullableResult:
即:
public Long getNullableResult(ResultSet rs, String columnName) throws SQLException {
return rs.getLong(columnName);
}
最后在applyPropertyMappings方法中执行metaObject.setValue(property, value);
metaValue.setValue方法最后会调用到Java类中对应数据域的set方法,这样也就完成了SQL查询结果集的Java类封装过程,过程中用到了反射。