1. 时序图
2. 增删改查
@Test
public void test() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// 1、获取 sqlSessionFactory 对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 2、获取 sqlSession 对象
SqlSession openSession = sqlSessionFactory.openSession();
try {
// 3、获取接口的实现类
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
// 4、执行目标方法 ------> 2.1
Employee employee = mapper.getEmpById(1);
System.out.println(employee);
} finally {
openSession.close();
}
}
2.1 MapperProxy#invoke
-
org.apache.ibatis.binding.MapperProxy#invoke
-
由于通过 getMapper() 获取的都是 MapperProxy 类型的代理类,所以会进入此方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 如果是 object 类的方法,就跳过代理
if (Object.class.equals(method.getDeclaringClass())) {
try {
return method.invoke(this, args);
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
}
// 从缓存中获取 mapperMethod ------> 2.2
final MapperMethod mapperMethod = cachedMapperMethod(method);
// 执行 execute 方法 ------> 2.3
return mapperMethod.execute(sqlSession, args);
}
2.2 MapperProxy#cachedMapperMethod
- org.apache.ibatis.binding.MapperProxy#cachedMapperMethod
private MapperMethod cachedMapperMethod(Method method) {
// 从缓存中获取 mapperMethod
MapperMethod mapperMethod = methodCache.get(method);
if (mapperMethod == null) {
// 创建 MapperMethod ------> 3
mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());
methodCache.put(method, mapperMethod);
}
return mapperMethod;
}
2.3 MapperMethod#execute
- org.apache.ibatis.binding.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 {
// 参数转换 ------> 4
Object param = method.convertArgsToSqlCommandParam(args);
// 调用查询方法 ------> 5
result = sqlSession.selectOne(command.getName(), param);
}
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;
}
3. 创建 MapperMethod
3.1 MapperMethod#MapperMethod
- org.apache.ibatis.binding.MapperMethod
public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {
// 创建 SqlCommand ------> 3.2
this.command = new SqlCommand(config, mapperInterface, method);
// 创建 MethodSignature ------> 3.3
this.method = new MethodSignature(config, mapperInterface, method);
}
3.2 SqlCommand#SqlCommand
- org.apache.ibatis.binding.MapperMethod.SqlCommand
public SqlCommand(Configuration configuration, Class<?> mapperInterface, Method method) {
// 构建 statementName,类似于 pers.mangseng.study.mybatis.mapper.EmployeeMapper.getEmpById
String statementName = mapperInterface.getName() + "." + method.getName();
MappedStatement ms = null;
if (configuration.hasStatement(statementName)) {
// 从 configuration 中获取 mappedStatement
ms = configuration.getMappedStatement(statementName);
} else if (!mapperInterface.equals(method.getDeclaringClass())) { // issue #35
String parentStatementName = method.getDeclaringClass().getName() + "." + method.getName();
if (configuration.hasStatement(parentStatementName)) {
ms = configuration.getMappedStatement(parentStatementName);
}
}
if (ms == null) {
if(method.getAnnotation(Flush.class) != null){
name = null;
type = SqlCommandType.FLUSH;
} else {
throw new BindingException("Invalid bound statement (not found): " + statementName);
}
} else {
name = ms.getId();
// 获取增删改查类型
type = ms.getSqlCommandType();
if (type == SqlCommandType.UNKNOWN) {
throw new BindingException("Unknown execution method for: " + name);
}
}
}
3.3 MethodSignature#MethodSignature
- org.apache.ibatis.binding.MapperMethod.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.mapKey = getMapKey(method);
this.returnsMap = (this.mapKey != null);
this.rowBoundsIndex = getUniqueParamIndex(method, RowBounds.class);
this.resultHandlerIndex = getUniqueParamIndex(method, ResultHandler.class);
// 创建 ParamNameResolver,并解析入参 ------> 3.4
this.paramNameResolver = new ParamNameResolver(configuration, method);
}
3.4 ParamNameResolver#ParamNameResolver
- org.apache.ibatis.reflection.ParamNameResolver
public ParamNameResolver(Configuration config, Method method) {
final Class<?>[] paramTypes = method.getParameterTypes();
// 获取参数上的注解
final Annotation[][] paramAnnotations = method.getParameterAnnotations();
final SortedMap<Integer, String> map = new TreeMap<Integer, String>();
int paramCount = paramAnnotations.length;
// get names from @Param annotations
for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) {
if (isSpecialParameter(paramTypes[paramIndex])) {
// skip special parameters
continue;
}
String name = null;
for (Annotation annotation : paramAnnotations[paramIndex]) {
// 判断注解是否属于 Param
if (annotation instanceof Param) {
hasParamAnnotation = true;
name = ((Param) annotation).value();
break;
}
}
if (name == null) {
// @Param was not specified.
if (config.isUseActualParamName()) {
name = getActualParamName(method, paramIndex);
}
if (name == null) {
// 如果 name 为 null,name 则等于 map 的 size,从 0 开始增长
name = String.valueOf(map.size());
}
}
// 添加到 map 中
map.put(paramIndex, name);
}
// 把解析后的 map 赋值给 names
names = Collections.unmodifiableSortedMap(map);
}
4. 参数转换
4.1 MethodSignature#convertArgsToSqlCommandParam
- org.apache.ibatis.binding.MapperMethod.MethodSignature
public Object convertArgsToSqlCommandParam(Object[] args) {
// 调用 paramNameResolver.getNamedParams() 方法 ------> 4.2
return paramNameResolver.getNamedParams(args);
}
4.2 ParamNameResolver#getNamedParams
- org.apache.ibatis.reflection.ParamNameResolver
public Object getNamedParams(Object[] args) {
final int paramCount = names.size();
if (args == null || paramCount == 0) {
return null;
} else if (!hasParamAnnotation && paramCount == 1) {
// 如果参数只有一个,就直接返回
return args[names.firstKey()];
} else {
// 如果参数有多个,就返回一个 map
final Map<String, Object> param = new ParamMap<Object>();
int i = 0;
for (Map.Entry<Integer, String> entry : names.entrySet()) {
// names 就是刚刚 3.4 节中分析出来的
param.put(entry.getValue(), args[entry.getKey()]);
// add generic param names (param1, param2, ...)
final String genericParamName = GENERIC_NAME_PREFIX + String.valueOf(i + 1);
// ensure not to overwrite parameter named with @Param
if (!names.containsValue(genericParamName)) {
// 添加一个 genericParamName,形如 param1, param2, ...,是从 1 开始
param.put(genericParamName, args[entry.getKey()]);
}
i++;
}
return param;
}
}
5. 查询
5.1 DefaultSqlSession#selectOne
- org.apache.ibatis.session.defaults.DefaultSqlSession
@Override
public <T> T selectOne(String statement, Object parameter) {
// 实际上也是调用 selectList() 方法进行查询 ------> 5.2
List<T> list = this.<T>selectList(statement, parameter);
if (list.size() == 1) {
// 如果 list.size() 为 1,则返回
return list.get(0);
} else if (list.size() > 1) {
// 如果大于 1,由于调用的是 selectOne() 方法,则抛出异常
throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
} else {
return null;
}
}
5.2 DefaultSqlSession#selectList
- org.apache.ibatis.session.defaults.DefaultSqlSession#selectList
@Override
public <E> List<E> selectList(String statement, Object parameter) {
// 调用重载方法 ------> 5.3
return this.selectList(statement, parameter, RowBounds.DEFAULT);
}
5.3 DefaultSqlSession#selectList
- org.apache.ibatis.session.defaults.DefaultSqlSession#selectList
@Override
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
try {
// 从 configuration 中获取 MappedStatement,每个 MappedStatement 就对应一个 增删改查标签
MappedStatement ms = configuration.getMappedStatement(statement);
// 执行 query 方法 ------> 5.4
return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
5.4 CachingExecutor#query
- org.apache.ibatis.executor.CachingExecutor
@Override
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
// 获取 sql 标签,其实就是 sql
BoundSql boundSql = ms.getBoundSql(parameterObject);
// 创建缓存 key,实际上调用 BaseExecutor 的方法创建
CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
// 继续调用重载的 query 方法 ------> 5.5
return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
5.5 CachingExecutor#query
- org.apache.ibatis.executor.CachingExecutor
@Override
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
throws SQLException {
// 二级缓存作用点
Cache cache = ms.getCache();
if (cache != null) {
flushCacheIfRequired(ms);
if (ms.isUseCache() && resultHandler == null) {
ensureNoOutParams(ms, parameterObject, boundSql);
@SuppressWarnings("unchecked")
List<E> list = (List<E>) tcm.getObject(cache, key);
if (list == null) {
list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
tcm.putObject(cache, key, list); // issue #578 and #116
}
return list;
}
}
// 调用 BaseExecutor 的 query 方法 ------> 5.6
return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
5.6 BaseExecutor#query
- org.apache.ibatis.executor.BaseExecutor
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
if (closed) {
throw new ExecutorException("Executor was closed.");
}
if (queryStack == 0 && ms.isFlushCacheRequired()) {
clearLocalCache();
}
List<E> list;
try {
queryStack++;
list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
if (list != null) {
// 一级缓存作用点
handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
} else {
// 从数据库中查询 ------> 5.7
list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
} finally {
queryStack--;
}
...
return list;
}
5.7 BaseExecutor#queryFromDatabase
- org.apache.ibatis.executor.BaseExecutor
private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
List<E> list;
localCache.putObject(key, EXECUTION_PLACEHOLDER);
try {
// 调用 doQuery 方法 ------> 5.8
list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
} finally {
// 每次查询后都 remove 缓存
localCache.removeObject(key);
}
// 再重新放入缓存中
localCache.putObject(key, list);
if (ms.getStatementType() == StatementType.CALLABLE) {
localOutputParameterCache.putObject(key, parameter);
}
return list;
}
5.8 SimpleExecutor#doQuery
- org.apache.ibatis.executor.SimpleExecutor
@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();
// 创建其他三大 Handler 对象 ------> 6
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
// 处理预编译参数 ------> 7
stmt = prepareStatement(handler, ms.getStatementLog());
// 调用查询方法 ------> 5.9
return handler.<E>query(stmt, resultHandler);
} finally {
closeStatement(stmt);
}
}
5.9 RoutingStatementHandler#query
- org.apache.ibatis.executor.statement.RoutingStatementHandler
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
// 调用 PreparedStatementHandler 的 query 方法 ------> 5.10
return delegate.<E>query(statement, resultHandler);
}
5.10 PreparedStatementHandler#query
- org.apache.ibatis.executor.statement.PreparedStatementHandler#query
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
// 执行调用 jdbc 的 execute 方法进行查询
ps.execute();
// 用 resultHandler 处理结果集后返回 ------> 8
return resultSetHandler.<E> handleResultSets(ps);
}
6. 创建三大 Handler 对象
6.1 Configuration#newStatementHandler
-
org.apache.ibatis.session.Configuration
-
用于执行 SQL 语句
public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
// 创建 StatementHandler ------> 6.2
StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
// 用插件包装 statementHandler 后返回
statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
return statementHandler;
}
6.2 RoutingStatementHandler#RoutingStatementHandler
- org.apache.ibatis.executor.statement.RoutingStatementHandler
public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
switch (ms.getStatementType()) {
case STATEMENT:
delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
case PREPARED:
// 创建一个 PreparedStatementHandler ------> 6.3
delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
case CALLABLE:
delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
default:
throw new ExecutorException("Unknown statement type: " + ms.getStatementType());
}
}
6.3 PreparedStatementHandler#PreparedStatementHandler
- org.apache.ibatis.executor.statement.PreparedStatementHandler
public PreparedStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
// 调用父类 BaseStatementHandler 的初始化方法 ------> 6.4
super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
}
6.4 BaseStatementHandler#BaseStatementHandler
- org.apache.ibatis.executor.statement.BaseStatementHandler
protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
...
// 创建一个 parameterHandler ------> 6.5
this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
// 创建一个 resultSetHandler ------> 6.6
this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
}
6.5 Configuration#newParameterHandler
-
org.apache.ibatis.session.Configuration
-
用于处理 SQL 的参数
public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
// 创建 parameterHandler
ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql);
// 用插件包装 parameterHandler 后返回
parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler);
return parameterHandler;
}
6.6 Configuration#newResultSetHandler
-
org.apache.ibatis.session.Configuration
-
用于处理 SQL 的返回结果集
public ResultSetHandler newResultSetHandler(Executor executor, MappedStatement mappedStatement, RowBounds rowBounds, ParameterHandler parameterHandler,
ResultHandler resultHandler, BoundSql boundSql) {
// 创建 resultSetHandler
ResultSetHandler resultSetHandler = new DefaultResultSetHandler(executor, mappedStatement, parameterHandler, resultHandler, boundSql, rowBounds);
// 用插件包装 resultSetHandler 后返回
resultSetHandler = (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler);
return resultSetHandler;
}
7. 处理预编译参数
7.1 SimpleExecutor#prepareStatement
- org.apache.ibatis.executor.SimpleExecutor
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Statement stmt;
Connection connection = getConnection(statementLog);
stmt = handler.prepare(connection, transaction.getTimeout());
// 处理参数 ------> 7.2
handler.parameterize(stmt);
return stmt;
}
7.2 RoutingStatementHandler#parameterize
- org.apache.ibatis.executor.statement.RoutingStatementHandler
@Override
public void parameterize(Statement statement) throws SQLException {
//调用 PreparedStatementHandler 的 parameterize() 方法设置值 ------> 7.3
delegate.parameterize(statement);
}
7.3 PreparedStatementHandler#parameterize
- org.apache.ibatis.executor.statement.PreparedStatementHandler
@Override
public void parameterize(Statement statement) throws SQLException {
// 调用 DefaultParameterHandler 的 setParameters() 方法 ------> 7.4
parameterHandler.setParameters((PreparedStatement) statement);
}
7.4 DefaultParameterHandler#setParameters
- org.apache.ibatis.scripting.defaults.DefaultParameterHandler
public void setParameters(PreparedStatement ps) {
ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
if (parameterMappings != null) {
for (int i = 0; i < parameterMappings.size(); i++) {
// 循环处理参数值
ParameterMapping parameterMapping = parameterMappings.get(i);
if (parameterMapping.getMode() != ParameterMode.OUT) {
...
// 获取 typeHandler
TypeHandler typeHandler = parameterMapping.getTypeHandler();
// 获取 jdbcType
JdbcType jdbcType = parameterMapping.getJdbcType();
if (value == null && jdbcType == null) {
jdbcType = configuration.getJdbcTypeForNull();
}
try {
// 调用 BaseTypeHandler 设置值 ------> 7.5
typeHandler.setParameter(ps, i + 1, value, jdbcType);
} catch (TypeException e) {
throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
} catch (SQLException e) {
throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
}
}
}
}
}
7.5 BaseTypeHandler#setParameter
- org.apache.ibatis.type.BaseTypeHandler
@Override
public void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
...
try {
// 调用 UnknownTypeHandler 设置值 ------> 7.6,7.7
setNonNullParameter(ps, i, parameter, jdbcType);
} catch (Exception e) {
throw new TypeException("Error setting non null for parameter #" + i + " with JdbcType " + jdbcType + " . " +
"Try setting a different JdbcType for this parameter or a different configuration property. " +
"Cause: " + e, e);
}
}
7.6 UnknownTypeHandler#setNonNullParameter
- org.apache.ibatis.type.UnknownTypeHandler
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)
throws SQLException {
// 根据 parameter 的类型和 jdbcType,从 typeHandlerRegistry 中能处理的的 handler
TypeHandler handler = resolveTypeHandler(parameter, jdbcType);
// 此时的 handler 不再是 baseTypeHandler,而是其具体的实现类 ------> 7.5
handler.setParameter(ps, i, parameter, jdbcType);
}
7.7 IntegerTypeHandler#setNonNullParameter
- org.apache.ibatis.type.IntegerTypeHandler
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Integer parameter, JdbcType jdbcType)
throws SQLException {
// jdbc 中的方法
ps.setInt(i, parameter);
}
8. 处理返回值
8.1 DefaultResultSetHandler#handleResultSets
- org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleResultSets
@Override
public List<Object> handleResultSets(Statement stmt) throws SQLException {
ErrorContext.instance().activity("handling results").object(mappedStatement.getId());
final List<Object> multipleResults = new ArrayList<Object>();
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);
// 处理结果 ------> 8.2
handleResultSet(rsw, resultMap, multipleResults, null);
rsw = getNextResultSet(stmt);
cleanUpAfterHandlingResultSet();
resultSetCount++;
}
...
return collapseSingleResultList(multipleResults);
}
8.2 DefaultResultSetHandler#handleResultSet
- org.apache.ibatis.executor.resultset.DefaultResultSetHandler
private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException {
try {
if (parentMapping != null) {
handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping);
} else {
if (resultHandler == null) {
DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);
// 处理结果映射 ------> 8.3
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());
}
}
8.3 DefaultResultSetHandler#handleRowValues
- org.apache.ibatis.executor.resultset.DefaultResultSetHandler
public void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
// 如果有嵌套结果查询,进入此方法
if (resultMap.hasNestedResultMaps()) {
ensureNoRowBounds();
checkResultHandler();
handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
} else {
// 简单结果查询,进入此方法 ------> 8.4
handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
}
}
8.4 DefaultResultSetHandler#handleRowValuesForSimpleResultMap
- org.apache.ibatis.executor.resultset.DefaultResultSetHandler
private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)
throws SQLException {
DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>();
skipRows(rsw.getResultSet(), rowBounds);
while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);
// 调用 getRowValue() ------> 8.5
Object rowValue = getRowValue(rsw, discriminatedResultMap);
storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
}
}
8.5 DefaultResultSetHandler#getRowValue
- org.apache.ibatis.executor.resultset.DefaultResultSetHandler
private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException {
final ResultLoaderMap lazyLoader = new ResultLoaderMap();
// 根据 resultMap 中的 type 属性,通过反射调用无参构造器创建一个空对象
Object resultObject = createResultObject(rsw, resultMap, lazyLoader, null);
if (resultObject != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
// 创建 metaObject
final MetaObject metaObject = configuration.newMetaObject(resultObject);
boolean foundValues = !resultMap.getConstructorResultMappings().isEmpty();
if (shouldApplyAutomaticMappings(resultMap, false)) {
// 给 foundValues 赋值 ------> 8.6
foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, null) || foundValues;
}
foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, null) || foundValues;
foundValues = lazyLoader.size() > 0 || foundValues;
// 赋值给 resultObject,真正要返回的对象
resultObject = foundValues ? resultObject : null;
return resultObject;
}
return resultObject;
}
8.6 DefaultResultSetHandler#applyAutomaticMappings
- org.apache.ibatis.executor.resultset.DefaultResultSetHandler
private boolean applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {
List<UnMappedColumnAutoMapping> autoMapping = createAutomaticMappings(rsw, resultMap, metaObject, columnPrefix);
boolean foundValues = false;
if (autoMapping.size() > 0) {
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)) {
// 利用反射调用 set 方法注入
metaObject.setValue(mapping.property, value);
}
}
}
return foundValues;
}