03.MyBatis 源码分析之增删改查

1. 时序图

03.MyBatis 源码分析之增删改查

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;
}
发布了37 篇原创文章 · 获赞 3 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/masteryourself/article/details/83586629