处理结果集的逻辑:ResultSetHandler---->TypeHandler
@Override
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
Statement stmt = null;
try {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
//这一步完成connection建立,statement对象的创建,参数的赋值操作
stmt = prepareStatement(handler, ms.getStatementLog());
//我们今天看者一行,如何将jdbc返回的resultSet对象处理为我们想要的java类型
return handler.query(stmt, resultHandler);
} finally {
closeStatement(stmt);
}
}
//在 PreparedStatementHandler 类中,我们使用的是默认的预编译的statement
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
return resultSetHandler.handleResultSets(ps);
}
public List<Object> handleResultSets(Statement stmt) throws SQLException {
ErrorContext.instance().activity("handling results").object(mappedStatement.getId());
//<select>标签的resultMap属性,可以指定多个值,多个值之间用 “,”分割
//我们一般一个seclect指定一个resultMap
final List<Object> multipleResults = new ArrayList<>();
int resultSetCount = 0;
//将jdbc返回结果,进行包装。
//对每一列,封装列名,java类型,jdbc类型
ResultSetWrapper rsw = getFirstResultSet(stmt);
//里面封装的就是我们java的结果类型,也就是我们XML中配置的 resultType或resultMap
//resultType外层是resultMap
List<ResultMap> resultMaps = mappedStatement.getResultMaps();
int resultMapCount = resultMaps.size();
validateResultMapsCount(rsw, resultMapCount);
//进行遍历,赋值
while (rsw != null && resultMapCount > resultSetCount) {
ResultMap resultMap = resultMaps.get(resultSetCount);
//jdbc类型转为java类型
handleResultSet(rsw, resultMap, multipleResults, null);
rsw = getNextResultSet(stmt);
cleanUpAfterHandlingResultSet();
resultSetCount++;
}
String[] resultSets = mappedStatement.getResultSets();
if (resultSets != null) {
while (rsw != null && resultSetCount < resultSets.length) {
ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]);
if (parentMapping != null) {
String nestedResultMapId = parentMapping.getNestedResultMapId();
ResultMap resultMap = configuration.getResultMap(nestedResultMapId);
handleResultSet(rsw, resultMap, null, parentMapping);
}
rsw = getNextResultSet(stmt);
cleanUpAfterHandlingResultSet();
resultSetCount++;
}
}
// 这一步就是根据list的大小做判断,如果为1,则取第一条数据出来。是一个list套list的结构
//我们的list中的数据:
//User{userCode='10', userName='zzx', createTime=Mon Dec 16 22:42:57 CST 2019, userType='00', mobile='13456879087'}
return collapseSingleResultList(multipleResults);
}
private List<Object> collapseSingleResultList(List<Object> multipleResults) {
return multipleResults.size() == 1 ? (List<Object>) multipleResults.get(0) : multipleResults;
}
我们重点看下如何将jdbc类型结果转为java类型:
private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException {
try {
// 处理嵌套结果映射,我们的级联操作等,一个resultMap中某个java属性
//是另一个resultMap负责映射的
//比如 Student中有一个school属性,school有另一个结果集映射
if (parentMapping != null) {
handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping);
} else {
if (resultHandler == null) {
//新建一个resultHandler对象,对结果进行处理
DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);
handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);
//将我们的结果集放入multipleResults这个 list中
multipleResults.add(defaultResultHandler.getResultList());
} else {
handleRowValues(rsw, resultMap, resultHandler, rowBounds, null);
}
}
} finally {
// issue #228 (close resultsets)
closeResultSet(rsw.getResultSet());
}
}
public void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
if (resultMap.hasNestedResultMaps()) { //处理级联sql结果级,嵌套的resultMap
ensureNoRowBounds();
checkResultHandler();
handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
} else {//我们是一个普通的结果集,走这个分支
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<>();
ResultSet resultSet = rsw.getResultSet();
//这一步是做逻辑分页用的,比如我们起始 1,那么会跳过第一行数据,
//从第二行开始。 new RowBound(1,2)
skipRows(resultSet, rowBounds);
//shouldProcessMoreRows()这个方法是进行判断逻辑分页结束的,比如我们这个应该13行数据,但是
//我们只取从 1开始,俩条数据
while (shouldProcessMoreRows(resultContext, rowBounds) && !resultSet.isClosed() && resultSet.next()) {
//这块就是我们jdbc遍历取结果的步骤,只不过在这里会做转java类型的操作
//这个是处理鉴别器标签的,结果集多态。我们这儿不做鉴别器处理
ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(resultSet, resultMap, null);
//根据反射进行映射,生成一个java的对象。将一行数据转换为一个java类型对象,POJO
//User{userCode='10', userName='zzx', createTime=Mon Dec 16 22:42:57 CST 2019, userType='00', mobile='13456879087'}
Object rowValue = getRowValue(rsw, discriminatedResultMap, null);
//将我们的行数据,加入到我们结果集list中 比如查到10条数据,最终
// list.add(0),list.add(1),...这样操作,我们最终得到一个list数据集
storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
}
}
/**
<resultMap id="modelTypeMap" type="com.javartisan.BaseModel">
<discriminator javaType="java.lang.Integer" column="modelType">
<case value="1" resultType="com.javartisan.Model1"/>
<case value="2" resultType="com.javartisan.Model2"/>
</discriminator>
</resultMap>
**/
可以对比下传统的jdbc的操作:
rs = statement.executeQuery("select * from test");
//执行sql查询语句,返回结果集
System.out.println("查询结果为:");
while(rs.next()) {
//循环操作结果集
string = rs.getString("id") + "——" + rs.getString("name");
System.out.println(string);
}
应用反射给java对象赋值的操作:
//将一行数据,应用反射转为java对象,同时给对象属性赋值
private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, String columnPrefix) throws SQLException {
final ResultLoaderMap lazyLoader = new ResultLoaderMap();
//应用反射,创建一个User对象,这时候属性值还没赋值
Object rowValue = createResultObject(rsw, resultMap, lazyLoader, columnPrefix);
if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
final MetaObject metaObject = configuration.newMetaObject(rowValue);
boolean foundValues = this.useConstructorMappings;
if (shouldApplyAutomaticMappings(resultMap, false)) {
//给每一个属性字段进行赋值操作
foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix) || foundValues;
}
foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix) || foundValues;
foundValues = lazyLoader.size() > 0 || foundValues;
rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null;
}
return rowValue;
}
private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException {
this.useConstructorMappings = false; // reset previous mapping result
final List<Class<?>> constructorArgTypes = new ArrayList<>();
final List<Object> constructorArgs = new ArrayList<>();
// 通过反射,new一个对象出来,这儿,就是new User() (因为我们返回的java类型是User)
Object resultObject = createResultObject(rsw, resultMap, constructorArgTypes, constructorArgs, columnPrefix);
if (resultObject != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();
for (ResultMapping propertyMapping : propertyMappings) {
// issue gcode #109 && issue #149
if (propertyMapping.getNestedQueryId() != null && propertyMapping.isLazy()) {
resultObject = configuration.getProxyFactory().createProxy(resultObject, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs);
break;
}
}
}
this.useConstructorMappings = resultObject != null && !constructorArgTypes.isEmpty(); // set current mapping result
return resultObject;
}
// 给属性字段赋值,赋值成功返回 true
private boolean applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {
//MetaObject 里面封装了User{userCode='null', userName='null', createTime=null, userType='null', mobile='null'}
//UnMappedColumnAutoMapping 这里面负责映射关系的维护,jdbc的列名,java的属性名,类型处理器
List<UnMappedColumnAutoMapping> autoMapping = createAutomaticMappings(rsw, resultMap, metaObject, columnPrefix);
boolean foundValues = false;
if (!autoMapping.isEmpty()) {
for (UnMappedColumnAutoMapping mapping : autoMapping) {
//根据列名找到对应列的值value,比如,我们的usercode列 值为1
final Object value = mapping.typeHandler.getResult(rsw.getResultSet(), mapping.column);
if (value != null) {
foundValues = true;
}
if (value != null || (configuration.isCallSettersOnNulls() && !mapping.primitive)) {
// gcode issue #377, call setter on nulls (value is not 'found')
//给属性字段,进行赋值 列名usercode对应的java属性是userCode,给其赋值
metaObject.setValue(mapping.property, value);
}
}
}
return foundValues;
}
来源:CSDN
作者:itw_zhangzx02
链接:https://blog.csdn.net/itw_zhangzx02/article/details/103830822