Mybatis源码(八)mybatis的查询的结果集的封装
作者:互联网
前面的博客介绍执行的流程的增删改查,但是由于结果的集的封装我们没有讲清楚,所以写一篇博客。来详细的说明一下。mybatis
的对查询的结果集的封装问题。前面的一篇博客介绍了mybatis
会根据返回值类型,来决定执行什么样的操作。至此我们看下有那几种的返回的类型,然后写出对应的测试的方法。具体的代码如下:
public class MapperMethod {
public static class MethodSignature {
public MethodSignature(Configuration configuration, Class<?> mapperInterface, Method method) {
Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, mapperInterface);
if (resolvedReturnType instanceof Class<?>) {
this.returnType = (Class<?>) resolvedReturnType;
} else if (resolvedReturnType instanceof ParameterizedType) {
this.returnType = (Class<?>) ((ParameterizedType) resolvedReturnType).getRawType();
} else {
this.returnType = method.getReturnType();
}
this.returnsVoid = void.class.equals(this.returnType);
this.returnsMany = configuration.getObjectFactory().isCollection(this.returnType) || this.returnType.isArray();
this.returnsCursor = Cursor.class.equals(this.returnType);
this.returnsOptional = Optional.class.equals(this.returnType);
this.mapKey = getMapKey(method);
this.returnsMap = this.mapKey != null;
this.rowBoundsIndex = getUniqueParamIndex(method, RowBounds.class);
this.resultHandlerIndex = getUniqueParamIndex(method, ResultHandler.class);
this.paramNameResolver = new ParamNameResolver(configuration, method);
}
}
}
可以看到返回的类型有类的类型,还有就是集合和数组的类型,然后就是游标的类型,Optional
的类型,Map
的类型。所以我们写出下面的测试的代码,具体如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="testResult.mapper.AdminMapper">
<select id="selectByList" resultType="testResult.entity.Admin">
select * from admin limit 3;
</select>
<select id="selectByMap" resultType="testResult.entity.Admin">
select * from admin limit 3;
</select>
<select id="selectById" parameterType="int" resultType="testResult.entity.Admin">
select * from admin where id = #{id};
</select>
<select id="selectByOption" resultType="testResult.entity.Admin">
select * from admin where id = #{id};
</select>
<select id="selectByCursor" resultType="testResult.entity.Admin">
select * from admin limit 3;
</select>
</mapper>
package testResult.mapper;
import org.apache.ibatis.annotations.MapKey;
import org.apache.ibatis.cursor.Cursor;
import testResult.entity.Admin;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public interface AdminMapper {
List<Admin> selectByList();
@MapKey("id")
Map<Long,Admin> selectByMap();
Admin selectById(int id);
Optional<Admin> selectByOption(int id);
Cursor<Admin> selectByCursor();
}
package testResult.main;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import testResult.mapper.AdminMapper;
import java.io.IOException;
import java.io.InputStream;
public class TestResultMain {
public static void main(String[] args) throws IOException {
String resource = "mybatis.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sessionFactory.openSession();
AdminMapper mapper = sqlSession.getMapper(AdminMapper.class);
System.out.println(mapper.selectById(1));
System.out.println(mapper.selectByOption(1));
System.out.println(mapper.selectByList());
System.out.println(mapper.selectByMap());
System.out.println(mapper.selectByCursor());
}
}
让我们开始我们的调试之旅,在调试之前,我们还是要了解一下resolvedReturnType
的值,怎么计算出来的。具体的是调用resolveReturnType(method, mapperInterface)
方法,我们跟进去看看,具体的代码如下:
public class TypeParameterResolver {
public static Type resolveReturnType(Method method, Type srcType) {
Type returnType = method.getGenericReturnType();
Class<?> declaringClass = method.getDeclaringClass();
return resolveType(returnType, srcType, declaringClass);
}
private static Type resolveType(Type type, Type srcType, Class<?> declaringClass) {
if (type instanceof TypeVariable) {
return resolveTypeVar((TypeVariable<?>) type, srcType, declaringClass);
} else if (type instanceof ParameterizedType) {
return resolveParameterizedType((ParameterizedType) type, srcType, declaringClass);
} else if (type instanceof GenericArrayType) {
return resolveGenericArrayType((GenericArrayType) type, srcType, declaringClass);
} else {
return type;
}
}
}
很明显这儿进过层层的调用最终返回的是testResult.entity.Admin
,这个时候返回到最初调用的方法的地方,具体的代码如下:
public class MapperMethod {
public static class MethodSignature {
public MethodSignature(Configuration configuration, Class<?> mapperInterface, Method method) {
Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, mapperInterface);
if (resolvedReturnType instanceof Class<?>) {
this.returnType = (Class<?>) resolvedReturnType;
} else if (resolvedReturnType instanceof ParameterizedType) {
this.returnType = (Class<?>) ((ParameterizedType) resolvedReturnType).getRawType();
} else {
this.returnType = method.getReturnType();
}
this.returnsVoid = void.class.equals(this.returnType);
this.returnsMany = configuration.getObjectFactory().isCollection(this.returnType) || this.returnType.isArray();
this.returnsCursor = Cursor.class.equals(this.returnType);
this.returnsOptional = Optional.class.equals(this.returnType);
this.mapKey = getMapKey(method);
this.returnsMap = this.mapKey != null;
this.rowBoundsIndex = getUniqueParamIndex(method, RowBounds.class);
this.resultHandlerIndex = getUniqueParamIndex(method, ResultHandler.class);
this.paramNameResolver = new ParamNameResolver(configuration, method);
}
}
}
上面走来的resolvedReturnType instanceof Class<?>
判断是满足的,然后将returnType
设置为testResult.entity.Admin
,然后下面的return
的属性都是为false
。这个时候有了这些值后,我们就一步步的去看结果集是如何封装的。具体的代码如下:
public class MapperMethod {
public Object execute(SqlSession sqlSession, Object[] args) {
Object result;
switch (command.getType()) {
case INSERT: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.insert(command.getName(), param));
break;
}
case UPDATE: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.update(command.getName(), param));
break;
}
case DELETE: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.delete(command.getName(), param));
break;
}
case SELECT:
if (method.returnsVoid() && method.hasResultHandler()) {
executeWithResultHandler(sqlSession, args);
result = null;
} else if (method.returnsMany()) {
result = executeForMany(sqlSession, args);
} else if (method.returnsMap()) {
result = executeForMap(sqlSession, args);
} else if (method.returnsCursor()) {
result = executeForCursor(sqlSession, args);
} else {
Object param = method.convertArgsToSqlCommandParam(args);
result = sqlSession.selectOne(command.getName(), param);
if (method.returnsOptional()
&& (result == null || !method.getReturnType().equals(result.getClass()))) {
result = Optional.ofNullable(result);
}
}
break;
case FLUSH:
result = sqlSession.flushStatements();
break;
default:
throw new BindingException("Unknown execution method for: " + command.getName());
}
if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
throw new BindingException("Mapper method '" + command.getName()
+ " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
}
return result;
}
}
上面代码会调用sqlSession.selectOne(command.getName(), param);
方法,具体的代码如下:
public class DefaultSqlSession implements SqlSession {
@Override
public <T> T selectOne(String statement, Object parameter) {
// Popular vote was to return null on 0 results and throw exception on too many.
List<T> list = this.selectList(statement, parameter);
if (list.size() == 1) {
return list.get(0);
} else if (list.size() > 1) {
throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
} else {
return null;
}
}
}
你会发现调用的还是selectList(statement, parameter);
方法,这个方法我们之前讲过,所以这儿就不详细说。想了解详情的,可以看前面的博客。然后我们直接看具体的处理的结果集的方法。具体的代码如下:
public class DefaultResultSetHandler implements ResultSetHandler {
@Override
public List<Object> handleResultSets(Statement stmt) throws SQLException {
ErrorContext.instance().activity("handling results").object(mappedStatement.getId());
//创建一个新的List的集合。
final List<Object> multipleResults = new ArrayList<>();
int resultSetCount = 0;
ResultSetWrapper rsw = getFirstResultSet(stmt);
List<ResultMap> resultMaps = mappedStatement.getResultMaps();
int resultMapCount = resultMaps.size();
validateResultMapsCount(rsw, resultMapCount);
while (rsw != null && resultMapCount > resultSetCount) {
ResultMap resultMap = resultMaps.get(resultSetCount);
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++;
}
}
return collapseSingleResultList(multipleResults);
}
}
上面的方法就是入参是查询完成的PreparedStatement
对象。这个总的方法我们需要好好看下。这个方法走来创建了一个空的list
的集合,然后调用的getFirstResultSet(stmt);
方法,这个方法返回一个 ResultSetWrapper
对象。这是一个对结果集的包装对象,同时也将传入进来的ps
对象传入到这个方法中去。具体的代码如下:
public class DefaultResultSetHandler implements ResultSetHandler {
private ResultSetWrapper getFirstResultSet(Statement stmt) throws SQLException {
//获取结果集
ResultSet rs = stmt.getResultSet();
while (rs == null) {
// move forward to get the first resultset in case the driver
// doesn't return the resultset as the first result (HSQLDB 2.1)
if (stmt.getMoreResults()) {
rs = stmt.getResultSet();
} else {
if (stmt.getUpdateCount() == -1) {
// no more results. Must be no resultset
break;
}
}
}
return rs != null ? new ResultSetWrapper(rs, configuration) : null;
}
}
上面的代码直接获取对应的结果集,然后由于是查询,这儿的结果集肯定不会空,于是会直接创建ResultSetWrapper
对象,这个时候,我们需要跟进这个类的构造方法中去。具体的代码如下:
public class ResultSetWrapper {
public ResultSetWrapper(ResultSet rs, Configuration configuration) throws SQLException {
super();
//获取类型的转换的类
this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
this.resultSet = rs;
//获取对应结果集的元数据
final ResultSetMetaData metaData = rs.getMetaData();
//获取列的列数
final int columnCount = metaData.getColumnCount();
//遍历列数
for (int i = 1; i <= columnCount; i++) {
//获取对应的列名添加到columnNames集合中去
columnNames.add(configuration.isUseColumnLabel() ? metaData.getColumnLabel(i) : metaData.getColumnName(i));
//获取对应的jdbctype添加到jdbctypes集合中去
jdbcTypes.add(JdbcType.forCode(metaData.getColumnType(i)));
//获取对应的列的类型添加到classNames集合中去
classNames.add(metaData.getColumnClassName(i));
}
}
}
上面的方法,最终将类型的转化器,列名,jdbctype
,每列的类名包装起来。最后组成ResultSetWrapper
返回,至此getFirstResultSet(stmt);
方法就结束了。我们继续看原来的代码。
public class DefaultResultSetHandler implements ResultSetHandler {
@Override
public List<Object> handleResultSets(Statement stmt) throws SQLException {
ErrorContext.instance().activity("handling results").object(mappedStatement.getId());
//创建一个新的List的集合。
final List<Object> multipleResults = new ArrayList<>();
int resultSetCount = 0;
//一些重要的参数包装起来
ResultSetWrapper rsw = getFirstResultSet(stmt);
//获取resultMap,这个是之前在读取XML的时候封装好的
List<ResultMap> resultMaps = mappedStatement.getResultMaps()
int resultMapCount = resultMaps.size();//1
//校验对应的对象
validateResultMapsCount(rsw, resultMapCount);
//遍历
while (rsw != null && resultMapCount > resultSetCount) {
ResultMap resultMap = resultMaps.get(resultSetCount);
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++;
}
}
return collapseSingleResultList(multipleResults);
}
}
上面的代码经过一系列的调用,最终执行 handleResultSet(rsw, resultMap, multipleResults, null);
方法,我们继续跟进去看看对应的代码,具体的代码如下:
public class DefaultResultSetHandler implements ResultSetHandler {
private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException {
try {
//传进来的值为null
if (parentMapping != null) {
handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping);
} else {
//这个值默认为null
if (resultHandler == null) {
//创建默认的结果集处理类 其中包含一个默认的list集合
DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);
//调用这个方法
handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);
multipleResults.add(defaultResultHandler.getResultList());
} else {
handleRowValues(rsw, resultMap, resultHandler, rowBounds, null);
}
}
} finally {
// issue #228 (close resultsets)
closeResultSet(rsw.getResultSet());
}
}
}
上面的方法最终会调用 handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);
这个方法,我们继续跟进,具体的代码如下:
public class DefaultResultSetHandler implements ResultSetHandler {
public void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
//resultMap中只有一条,所以这个if不会进
if (resultMap.hasNestedResultMaps()) {
ensureNoRowBounds();
checkResultHandler();
handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
} else {
handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
}
}
}
上面的代码经过一系列调用,最终调用的是handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
方法,具体的代码如下:
public class DefaultResultSetHandler implements ResultSetHandler {
private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)
throws SQLException {
//创建默认的结果集内容的对象
DefaultResultContext<Object> resultContext = new DefaultResultContext<>();
//获取结果集
ResultSet resultSet = rsw.getResultSet();
//跳过指定的页数
skipRows(resultSet, rowBounds);
//判读有没有下一页
while (shouldProcessMoreRows(resultContext, rowBounds) && !resultSet.isClosed() && resultSet.next()) {
//解析有问题的map
ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(resultSet, resultMap, null);
//获取对应行的值
Object rowValue = getRowValue(rsw, discriminatedResultMap, null);
storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
}
}
}
上面的代码重要的部分是获取对应行的值,调用getRowValue(rsw, discriminatedResultMap, null);
方法,我们继续跟进对应的代码,具体的代码如下:
public class DefaultResultSetHandler implements ResultSetHandler {
private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, String columnPrefix) throws SQLException {
//创建对应的对象
final ResultLoaderMap lazyLoader = new ResultLoaderMap();
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;
}
}
上面的代码会调用createResultObject(rsw, resultMap, lazyLoader, columnPrefix);
创建对应的对象,我们继续跟进去,具体的代码如下:
public class DefaultResultSetHandler implements ResultSetHandler {
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<>();
//创建结果集对象
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;
}
}
上面的代码经过一系列的调用,最终创建了结果集对象,只不过这个时候这个结果集对象没有对应的属性值,直接返回。我们继续看剩下的代码:
public class DefaultResultSetHandler implements ResultSetHandler {
private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, String columnPrefix) throws SQLException {
//创建对应的对象
final ResultLoaderMap lazyLoader = new ResultLoaderMap();
//创建结果集对象
Object rowValue = createResultObject(rsw, resultMap, lazyLoader, columnPrefix);
if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
//根据结果集对象创建MetaObject对象
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;
}
}
上面的代码会应用自动映射,这个时候会调用applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix)
方法,我们继续跟进去,具体的代码如下:
public class DefaultResultSetHandler implements ResultSetHandler {
private boolean applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {
//创建对应列的类型的类型转换器的list
List<UnMappedColumnAutoMapping> autoMapping = createAutomaticMappings(rsw, resultMap, metaObject, columnPrefix);
boolean foundValues = false;
//判断不为空
if (!autoMapping.isEmpty()) {
//遍历进行赋值
for (UnMappedColumnAutoMapping mapping : autoMapping) {
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')
//进行赋值
metaObject.setValue(mapping.property, value);
}
}
}
return foundValues;
}
}
上面的方法就是进行对应的列中的值进行赋值,然后返回foundValues
的值,只要赋值了这个值就为true
,然后返回到原来的代码的地方。具体的代码如下:
public class DefaultResultSetHandler implements ResultSetHandler {
private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, String columnPrefix) throws SQLException {
//创建对应的对象
final ResultLoaderMap lazyLoader = new ResultLoaderMap();
//创建结果集对象
Object rowValue = createResultObject(rsw, resultMap, lazyLoader, columnPrefix);
if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
//根据结果集对象创建MetaObject对象
final MetaObject metaObject = configuration.newMetaObject(rowValue);
boolean foundValues = this.useConstructorMappings;
//判断是否应该应用自动映射
if (shouldApplyAutomaticMappings(resultMap, false)) {
//对返回的结果集进行对应的赋值,只要有赋值,就会返回true
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;
}
}
上面的代码执行完,然后执行applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix)
方法,我们继续跟进对应的代码,具体的代码如下:
public class DefaultResultSetHandler implements ResultSetHandler {
private boolean applyPropertyMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, ResultLoaderMap lazyLoader, String columnPrefix)
throws SQLException {
final List<String> mappedColumnNames = rsw.getMappedColumnNames(resultMap, columnPrefix);//0
boolean foundValues = false;
final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();//0
for (ResultMapping propertyMapping : propertyMappings) {
String column = prependPrefix(propertyMapping.getColumn(), columnPrefix);
if (propertyMapping.getNestedResultMapId() != null) {
// the user added a column attribute to a nested result map, ignore it
column = null;
}
if (propertyMapping.isCompositeResult()
|| (column != null && mappedColumnNames.contains(column.toUpperCase(Locale.ENGLISH)))
|| propertyMapping.getResultSet() != null) {
Object value = getPropertyMappingValue(rsw.getResultSet(), metaObject, propertyMapping, lazyLoader, columnPrefix);
// issue #541 make property optional
final String property = propertyMapping.getProperty();
if (property == null) {
continue;
} else if (value == DEFERRED) {
foundValues = true;
continue;
}
if (value != null) {
foundValues = true;
}
if (value != null || (configuration.isCallSettersOnNulls() && !metaObject.getSetterType(property).isPrimitive())) {
// gcode issue #377, call setter on nulls (value is not 'found')
metaObject.setValue(property, value);
}
}
}
return foundValues;
}
}
取出来的长度都是0
直接返回foundValues
的值,foundValues
的值为true
,最后在返回到原来代码执行的地方
public class DefaultResultSetHandler implements ResultSetHandler {
private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, String columnPrefix) throws SQLException {
//创建对应的对象
final ResultLoaderMap lazyLoader = new ResultLoaderMap();
//创建结果集对象
Object rowValue = createResultObject(rsw, resultMap, lazyLoader, columnPrefix);
if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
//根据结果集对象创建MetaObject对象
final MetaObject metaObject = configuration.newMetaObject(rowValue);
boolean foundValues = this.useConstructorMappings;
//判断是否应该应用自动映射
if (shouldApplyAutomaticMappings(resultMap, false)) {
foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix) || foundValues;
}
//返回的是true
foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix) || foundValues;
foundValues = lazyLoader.size() > 0 || foundValues; // true
//直接将正确的结果集返回
rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null;
}
return rowValue;
}
}
上面的执行完成后,直接将封装好的对象直接返回,然后执行到如下的代码,具体如下:
public class DefaultResultSetHandler implements ResultSetHandler {
private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)
throws SQLException {
//创建默认的结果集内容的对象
DefaultResultContext<Object> resultContext = new DefaultResultContext<>();
//获取结果集
ResultSet resultSet = rsw.getResultSet();
//跳过指定的页数
skipRows(resultSet, rowBounds);
//判读有没有下一页
while (shouldProcessMoreRows(resultContext, rowBounds) && !resultSet.isClosed() && resultSet.next()) {
//解析有问题的map
ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(resultSet, resultMap, null);
//获取对应行的值
Object rowValue = getRowValue(rsw, discriminatedResultMap, null);
storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
}
}
}
上面的代码最后会执行storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
我们继续跟进去,查看具体的代码,具体的代码如下:
private void storeObject(ResultHandler<?> resultHandler, DefaultResultContext<Object> resultContext, Object rowValue, ResultMapping parentMapping, ResultSet rs) throws SQLException {
if (parentMapping != null) {
linkToParents(rs, parentMapping, rowValue);
} else {
callResultHandler(resultHandler, resultContext, rowValue);
}
}
private void callResultHandler(ResultHandler<?> resultHandler, DefaultResultContext<Object> resultContext, Object rowValue) {
resultContext.nextResultObject(rowValue);
((ResultHandler<Object>) resultHandler).handleResult(resultContext);
}
这个时候会将结果集添加到multipleResults
集合中,最后我们再回到原来的代码的执行的地方,具体的代码如下:
public class DefaultResultSetHandler implements ResultSetHandler {
private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException {
try {
//传进来的值为null
if (parentMapping != null) {
handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping);
} else {
//这个值默认为null
if (resultHandler == null) {
//创建默认的结果集处理类 其中包含一个默认的list集合
DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);
//调用这个方法
handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);
//添加到对应的集合中去
multipleResults.add(defaultResultHandler.getResultList());
} else {
handleRowValues(rsw, resultMap, resultHandler, rowBounds, null);
}
}
} finally {
// issue #228 (close resultsets)
//关闭rs
closeResultSet(rsw.getResultSet());
}
}
}
上面的代码就表示结果集封装完成。我们在回到原来执行的代码的地方,具体的代码如下:
public class DefaultResultSetHandler implements ResultSetHandler {
@Override
public List<Object> handleResultSets(Statement stmt) throws SQLException {
ErrorContext.instance().activity("handling results").object(mappedStatement.getId());
//创建一个新的List的集合。
final List<Object> multipleResults = new ArrayList<>();
int resultSetCount = 0;
ResultSetWrapper rsw = getFirstResultSet(stmt);
List<ResultMap> resultMaps = mappedStatement.getResultMaps();
int resultMapCount = resultMaps.size();
validateResultMapsCount(rsw, resultMapCount);
//循环结果集
while (rsw != null && resultMapCount > resultSetCount) {
ResultMap resultMap = resultMaps.get(resultSetCount);
//封装结果集
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++;
}
}
return collapseSingleResultList(multipleResults);
}
}
上面的循环会遍历所有的结果,一条条的封装,由于我们只返回一条数据,所以这个循环就结束了。最后将对应的结果集进行返回就行了,至此整个单条记录的封装就结束了。
我们继续看封装成Optional
对象的,至此我们会讲述不同的地方,相同的就直接略过。这个时候走来不一样的就是返回值的类型不一样,这个时候返回的类型就是参数化类型,参数化类型简单的说就是泛性。这个时候看下如下的代码
public class MapperMethod {
public static class MethodSignature {
public MethodSignature(Configuration configuration, Class<?> mapperInterface, Method method) {
Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, mapperInterface);
if (resolvedReturnType instanceof Class<?>) {
this.returnType = (Class<?>) resolvedReturnType;
} else if (resolvedReturnType instanceof ParameterizedType) {//参数化类型可以理解成泛性
//获取对应的原始类型(非泛性)
this.returnType = (Class<?>) ((ParameterizedType) resolvedReturnType).getRawType();
} else {
this.returnType = method.getReturnType();
}
this.returnsVoid = void.class.equals(this.returnType);
this.returnsMany = configuration.getObjectFactory().isCollection(this.returnType) || this.returnType.isArray();
this.returnsCursor = Cursor.class.equals(this.returnType);
this.returnsOptional = Optional.class.equals(this.returnType);
this.mapKey = getMapKey(method);
this.returnsMap = this.mapKey != null;
this.rowBoundsIndex = getUniqueParamIndex(method, RowBounds.class);
this.resultHandlerIndex = getUniqueParamIndex(method, ResultHandler.class);
this.paramNameResolver = new ParamNameResolver(configuration, method);
}
}
}
上面代码由于是返回的是optional
的类型的参数,所以这儿的returnType
的值为optional
,然后returnsOptional
的值为true
,然后其他为false
,同时对象为null
。我们继续跟进相应的代码。
public class MapperMethod {
public Object execute(SqlSession sqlSession, Object[] args) {
Object result;
switch (command.getType()) {
case INSERT: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.insert(command.getName(), param));
break;
}
case UPDATE: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.update(command.getName(), param));
break;
}
case DELETE: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.delete(command.getName(), param));
break;
}
case SELECT:
if (method.returnsVoid() && method.hasResultHandler()) {
executeWithResultHandler(sqlSession, args);
result = null;
} else if (method.returnsMany()) {
result = executeForMany(sqlSession, args);
} else if (method.returnsMap()) {
result = executeForMap(sqlSession, args);
} else if (method.returnsCursor()) {
result = executeForCursor(sqlSession, args);
} else {
Object param = method.convertArgsToSqlCommandParam(args);
result = sqlSession.selectOne(command.getName(), param);
if (method.returnsOptional()
&& (result == null || !method.getReturnType().equals(result.getClass()))) {
result = Optional.ofNullable(result);
}
}
break;
case FLUSH:
result = sqlSession.flushStatements();
break;
default:
throw new BindingException("Unknown execution method for: " + command.getName());
}
if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
throw new BindingException("Mapper method '" + command.getName()
+ " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
}
return result;
}
}
这个你会发现查询单条的原理是一样的,唯一不同的在最后有了一个判断,判断是不是optional
类,还有就是result
的值为空,或者返回的类型不是optional
类型,前面的条件满足就将结果封装成optional
对象。返回的结果是optional
对象就讲完了。
接下来我们看查询的返回值是list
的情况。具体的代码如下:
public class MapperMethod {
public static class MethodSignature {
public MethodSignature(Configuration configuration, Class<?> mapperInterface, Method method) {
Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, mapperInterface);
if (resolvedReturnType instanceof Class<?>) {
this.returnType = (Class<?>) resolvedReturnType;
} else if (resolvedReturnType instanceof ParameterizedType) {//参数化类型可以理解成泛性
//获取对应的原始类型(非泛性)
this.returnType = (Class<?>) ((ParameterizedType) resolvedReturnType).getRawType();
} else {
this.returnType = method.getReturnType();
}
this.returnsVoid = void.class.equals(this.returnType);
this.returnsMany = configuration.getObjectFactory().isCollection(this.returnType) || this.returnType.isArray();
this.returnsCursor = Cursor.class.equals(this.returnType);
this.returnsOptional = Optional.class.equals(this.returnType);
this.mapKey = getMapKey(method);
this.returnsMap = this.mapKey != null;
this.rowBoundsIndex = getUniqueParamIndex(method, RowBounds.class);
this.resultHandlerIndex = getUniqueParamIndex(method, ResultHandler.class);
this.paramNameResolver = new ParamNameResolver(configuration, method);
}
}
}
这个时候returnType
的值是list
,然后returnsMany
的值为true
,其他的都是一样的。然后我们看执行的逻辑,具体的代码如下:
public class MapperMethod {
public Object execute(SqlSession sqlSession, Object[] args) {
Object result;
switch (command.getType()) {
case INSERT: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.insert(command.getName(), param));
break;
}
case UPDATE: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.update(command.getName(), param));
break;
}
case DELETE: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.delete(command.getName(), param));
break;
}
case SELECT:
if (method.returnsVoid() && method.hasResultHandler()) {
executeWithResultHandler(sqlSession, args);
result = null;
} else if (method.returnsMany()) {
result = executeForMany(sqlSession, args);
} else if (method.returnsMap()) {
result = executeForMap(sqlSession, args);
} else if (method.returnsCursor()) {
result = executeForCursor(sqlSession, args);
} else {
Object param = method.convertArgsToSqlCommandParam(args);
result = sqlSession.selectOne(command.getName(), param);
if (method.returnsOptional()
&& (result == null || !method.getReturnType().equals(result.getClass()))) {
result = Optional.ofNullable(result);
}
}
break;
case FLUSH:
result = sqlSession.flushStatements();
break;
default:
throw new BindingException("Unknown execution method for: " + command.getName());
}
if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
throw new BindingException("Mapper method '" + command.getName()
+ " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
}
return result;
}
}
这个时候会执行executeForMany(sqlSession, args);
方法。最终逻辑还是一样的,需要注意的是,以下的循环会执行多次,具体的代码如下:
public class DefaultResultSetHandler implements ResultSetHandler {
private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)
throws SQLException {
//创建默认的结果集内容的对象
DefaultResultContext<Object> resultContext = new DefaultResultContext<>();
//获取结果集
ResultSet resultSet = rsw.getResultSet();
//跳过指定的页数
skipRows(resultSet, rowBounds);
//判读有没有下一项
while (shouldProcessMoreRows(resultContext, rowBounds) && !resultSet.isClosed() && resultSet.next()) {
//解析有问题的map
ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(resultSet, resultMap, null);
//获取对应行的值
Object rowValue = getRowValue(rsw, discriminatedResultMap, null);
storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
}
}
}
这儿会将查出来的东西,全部遍历封装到指定的对象中去。最后添加到defaultResultHandler
中去,然后返回,最后存入multipleResults
集合中去。最后将这个集合进行返回。至此返回list
的集合执行完成。
接下来看的就会死返回的是map
的类型,我们继续看如下的代码
public class MapperMethod {
public static class MethodSignature {
public MethodSignature(Configuration configuration, Class<?> mapperInterface, Method method) {
Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, mapperInterface);
if (resolvedReturnType instanceof Class<?>) {
this.returnType = (Class<?>) resolvedReturnType;
} else if (resolvedReturnType instanceof ParameterizedType) {//参数化类型可以理解成泛性
//获取对应的原始类型(非泛性)
this.returnType = (Class<?>) ((ParameterizedType) resolvedReturnType).getRawType();
} else {
this.returnType = method.getReturnType();
}
this.returnsVoid = void.class.equals(this.returnType);
this.returnsMany = configuration.getObjectFactory().isCollection(this.returnType) || this.returnType.isArray();
this.returnsCursor = Cursor.class.equals(this.returnType);
this.returnsOptional = Optional.class.equals(this.returnType);
//这个时候获取的mapKey为id,我加了对应的注解
this.mapKey = getMapKey(method);
this.returnsMap = this.mapKey != null;
this.rowBoundsIndex = getUniqueParamIndex(method, RowBounds.class);
this.resultHandlerIndex = getUniqueParamIndex(method, ResultHandler.class);
this.paramNameResolver = new ParamNameResolver(configuration, method);
}
}
}
这个时候returnType
的值为Map
,然后mapKey
为id
,然后returnsMap
的值为true
,我们继续跟进对应的代码,具体的代码如下:
public class MapperMethod {
public Object execute(SqlSession sqlSession, Object[] args) {
Object result;
switch (command.getType()) {
case INSERT: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.insert(command.getName(), param));
break;
}
case UPDATE: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.update(command.getName(), param));
break;
}
case DELETE: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.delete(command.getName(), param));
break;
}
case SELECT:
if (method.returnsVoid() && method.hasResultHandler()) {
executeWithResultHandler(sqlSession, args);
result = null;
} else if (method.returnsMany()) {
result = executeForMany(sqlSession, args);
} else if (method.returnsMap()) {
result = executeForMap(sqlSession, args);
} else if (method.returnsCursor()) {
result = executeForCursor(sqlSession, args);
} else {
Object param = method.convertArgsToSqlCommandParam(args);
result = sqlSession.selectOne(command.getName(), param);
if (method.returnsOptional()
&& (result == null || !method.getReturnType().equals(result.getClass()))) {
result = Optional.ofNullable(result);
}
}
break;
case FLUSH:
result = sqlSession.flushStatements();
break;
default:
throw new BindingException("Unknown execution method for: " + command.getName());
}
if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
throw new BindingException("Mapper method '" + command.getName()
+ " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
}
return result;
}
}
这个时候上面会执行executeForMap(sqlSession, args);
方法。我们继续跟进去对应的代码,具体的代码如下:
public class MapperMethod {
private <K, V> Map<K, V> executeForMap(SqlSession sqlSession, Object[] args) {
Map<K, V> result;
Object param = method.convertArgsToSqlCommandParam(args);
if (method.hasRowBounds()) {
RowBounds rowBounds = method.extractRowBounds(args);
result = sqlSession.selectMap(command.getName(), param, method.getMapKey(), rowBounds);
} else {
result = sqlSession.selectMap(command.getName(), param, method.getMapKey());
}
return result;
}
}
因为没有分页,所以这儿会执行的else
中查询Map
的的方法, sqlSession.selectMap(command.getName(), param, method.getMapKey());
我们继续跟进对应的代码,具体的代码如下:
public class DefaultSqlSession implements SqlSession {
@Override
public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
final List<? extends V> list = selectList(statement, parameter, rowBounds);
final DefaultMapResultHandler<K, V> mapResultHandler = new DefaultMapResultHandler<>(mapKey,
configuration.getObjectFactory(), configuration.getObjectWrapperFactory(), configuration.getReflectorFactory());
final DefaultResultContext<V> context = new DefaultResultContext<>();
for (V o : list) {
context.nextResultObject(o);
mapResultHandler.handleResult(context);
}
return mapResultHandler.getMappedResults();
}
}
- 上面调用
selectList(statement, parameter, rowBounds);
方法就是我们之前看的查询的方法,然后创建两个对象。然后遍历这个list
,我们现在要的看的方法就是context.nextResultObject(o);
具体的代码如下:
public class DefaultResultContext<T> implements ResultContext<T> {
public void nextResultObject(T resultObject) {
resultCount++;
this.resultObject = resultObject;
}
}
取出对应的值包装到DefaultResultContext
对象中去,然后将resultCount++
;,这个时候我们需要看的是mapResultHandler.handleResult(context);
具体的代码如下:
public class DefaultMapResultHandler<K, V> implements ResultHandler<V> {
@Override
public void handleResult(ResultContext<? extends V> context) {
//取出刚才包装的对象
final V value = context.getResultObject();
//获取对应的元数据
final MetaObject mo = MetaObject.forObject(value, objectFactory, objectWrapperFactory, reflectorFactory);
// TODO is that assignment always true?
//根据对应mapKey取出对象的值
final K key = (K) mo.getValue(mapKey);
//放入对应的Map集合中去
mappedResults.put(key, value);
}
}
走来取出刚才的包装的对象,然后取出对应mapKey
在对象中值作为键,然后添加到mappedResults
的map
中去。最终进行返回。至此包装Map
就讲完了。
最后我们再来讲下返回的类型是游标的类型,具体的代码如下:
public class MapperMethod {
public static class MethodSignature {
public MethodSignature(Configuration configuration, Class<?> mapperInterface, Method method) {
Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, mapperInterface);
if (resolvedReturnType instanceof Class<?>) {
this.returnType = (Class<?>) resolvedReturnType;
} else if (resolvedReturnType instanceof ParameterizedType) {//参数化类型可以理解成泛性
//获取对应的原始类型(非泛性)
this.returnType = (Class<?>) ((ParameterizedType) resolvedReturnType).getRawType();
} else {
this.returnType = method.getReturnType();
}
this.returnsVoid = void.class.equals(this.returnType);
this.returnsMany = configuration.getObjectFactory().isCollection(this.returnType) || this.returnType.isArray();
//返回的类型是Cursor对象
this.returnsCursor = Cursor.class.equals(this.returnType);
this.returnsOptional = Optional.class.equals(this.returnType);
this.mapKey = getMapKey(method);
this.returnsMap = this.mapKey != null;
this.rowBoundsIndex = getUniqueParamIndex(method, RowBounds.class);
this.resultHandlerIndex = getUniqueParamIndex(method, ResultHandler.class);
this.paramNameResolver = new ParamNameResolver(configuration, method);
}
}
}
这个时候returnType
的类型是Cursor
类型,然后returnsCursor
为true
,我们继续看查询的代码,具体如下:
public class MapperMethod {
public Object execute(SqlSession sqlSession, Object[] args) {
Object result;
switch (command.getType()) {
case INSERT: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.insert(command.getName(), param));
break;
}
case UPDATE: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.update(command.getName(), param));
break;
}
case DELETE: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.delete(command.getName(), param));
break;
}
case SELECT:
if (method.returnsVoid() && method.hasResultHandler()) {
executeWithResultHandler(sqlSession, args);
result = null;
} else if (method.returnsMany()) {
result = executeForMany(sqlSession, args);
} else if (method.returnsMap()) {
result = executeForMap(sqlSession, args);
} else if (method.returnsCursor()) {
result = executeForCursor(sqlSession, args);
} else {
Object param = method.convertArgsToSqlCommandParam(args);
result = sqlSession.selectOne(command.getName(), param);
if (method.returnsOptional()
&& (result == null || !method.getReturnType().equals(result.getClass()))) {
result = Optional.ofNullable(result);
}
}
break;
case FLUSH:
result = sqlSession.flushStatements();
break;
default:
throw new BindingException("Unknown execution method for: " + command.getName());
}
if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
throw new BindingException("Mapper method '" + command.getName()
+ " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
}
return result;
}
}
这个时候由于返回的结果是游标的类型,所以这儿会执行executeForCursor(sqlSession, args);
这个方法,具体的代码如下:
public class MapperMethod {
private <T> Cursor<T> executeForCursor(SqlSession sqlSession, Object[] args) {
Cursor<T> result;
Object param = method.convertArgsToSqlCommandParam(args);
if (method.hasRowBounds()) {
RowBounds rowBounds = method.extractRowBounds(args);
result = sqlSession.selectCursor(command.getName(), param, rowBounds);
} else {
result = sqlSession.selectCursor(command.getName(), param);
}
return result;
}
}
由于这儿没有分页,所以会直接执行sqlSession.selectCursor(command.getName(), param);
具体的代码如下:
public class DefaultSqlSession implements SqlSession {
@Override
public <T> Cursor<T> selectCursor(String statement, Object parameter) {
return selectCursor(statement, parameter, RowBounds.DEFAULT);
}
@Override
public <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds) {
try {
MappedStatement ms = configuration.getMappedStatement(statement);
Cursor<T> cursor = executor.queryCursor(ms, wrapCollection(parameter), rowBounds);
registerCursor(cursor);
return cursor;
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
}
然后会调用executor.queryCursor(ms, wrapCollection(parameter), rowBounds);
方法,具体的代码如下:
public class CachingExecutor implements Executor {
@Override
public <E> Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException {
flushCacheIfRequired(ms);
return delegate.queryCursor(ms, parameter, rowBounds);
}
}
然后会调用delegate.queryCursor(ms, parameter, rowBounds);
具体的代码如下:
public class SimpleExecutor extends BaseExecutor {
@Override
protected <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql) throws SQLException {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, null, boundSql);
Statement stmt = prepareStatement(handler, ms.getStatementLog());
stmt.closeOnCompletion();
return handler.queryCursor(stmt);
}
}
这个时候会执行 handler.queryCursor(stmt);
方法,具体的代码如下:
public class RoutingStatementHandler implements StatementHandler {
@Override
public <E> Cursor<E> queryCursor(Statement statement) throws SQLException {
return delegate.queryCursor(statement);
}
}
public class PreparedStatementHandler extends BaseStatementHandler {
@Override
public <E> Cursor<E> queryCursor(Statement statement) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
return resultSetHandler.handleCursorResultSets(ps);
}
}
上面的代码会执行resultSetHandler.handleCursorResultSets(ps);
我们继续跟进对应的代码,具体的代码如下:
public class DefaultResultSetHandler implements ResultSetHandler {
@Override
public <E> Cursor<E> handleCursorResultSets(Statement stmt) throws SQLException {
ErrorContext.instance().activity("handling cursor results").object(mappedStatement.getId());
ResultSetWrapper rsw = getFirstResultSet(stmt);
List<ResultMap> resultMaps = mappedStatement.getResultMaps();
int resultMapCount = resultMaps.size();
validateResultMapsCount(rsw, resultMapCount);
if (resultMapCount != 1) {
throw new ExecutorException("Cursor results cannot be mapped to multiple resultMaps");
}
ResultMap resultMap = resultMaps.get(0);
return new DefaultCursor<>(this, resultMap, rsw, rowBounds);
}
}
上面的代码和前面的代码是如此的相似,这儿直接略过了。然后创建DefaultCursor
对象,我们直接跟进去,具体的代码如下:
public class DefaultCursor<T> implements Cursor<T> {
public DefaultCursor(DefaultResultSetHandler resultSetHandler, ResultMap resultMap, ResultSetWrapper rsw, RowBounds rowBounds) {
this.resultSetHandler = resultSetHandler;
this.resultMap = resultMap;
this.rsw = rsw;
this.rowBounds = rowBounds;
}
}
这个时候就创建好了DefaultCursor
的游标对象,然后直接返回。最后直接执行registerCursor
方法,具体的代码如下:
public class DefaultSqlSession implements SqlSession {
private <T> void registerCursor(Cursor<T> cursor) {
if (cursorList == null) {
cursorList = new ArrayList<>();
}
cursorList.add(cursor);
}
}
至此整个结果集的封装已经讲完了。下篇博客会讲下mybatis
的一些面试题。
标签:rsw,public,class,Mybatis,源码,result,mybatis,null,method 来源: https://blog.csdn.net/qq_33762302/article/details/113748014