spring-mybatis-3 (mapper接口的代理和mapper接口的方法执行和sql返回值的封装)


MapperScannerConfigurer
org.mybatis.spring.mapper.MapperScannerConfigurer#postProcessBeanDefinitionRegistry

  @Override
  public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    if (this.processPropertyPlaceHolders) {
      processPropertyPlaceHolders();
    }

    ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
    scanner.setAddToConfig(this.addToConfig);
    //指定扫描的注解
    scanner.setAnnotationClass(this.annotationClass);
    //指定扫描的接口
    scanner.setMarkerInterface(this.markerInterface);
    scanner.setSqlSessionFactory(this.sqlSessionFactory);
    scanner.setSqlSessionTemplate(this.sqlSessionTemplate);
    scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);
    scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);
    scanner.setResourceLoader(this.applicationContext);
    scanner.setBeanNameGenerator(this.nameGenerator);
    //指定的注解进行注册
    scanner.registerFilters();
    // 解析配置的mapper接口包
  scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage,  	    	
             ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
  }

org.mybatis.spring.mapper.ClassPathMapperScanner#doScan

//将包下的class变为 beanDefinitions 
Set<BeanDefinitionHolder> beanDefinitions = 
//调用 ClassPathBeanDefinitionScanner#doScan
super.doScan(basePackages);

//查看该方法
processBeanDefinitions(beanDefinitions);

查看
org.mybatis.spring.mapper.ClassPathMapperScanner#processBeanDefinitions

//对 BeanDefinition 的属性进行填充值
 for (BeanDefinitionHolder holder : beanDefinitions) {
        definition = (GenericBeanDefinition) holder.getBeanDefinition();
        definition.getConstructorArgumentValues()
                   .addGenericArgumentValue(definition.getBeanClassName()); // issue #59
      // 注册了 mapperFactoryBean class,这个是 Mapper 接口代理实例的入口类       
      // mapperFactoryBean 中的 MapperFactoryBean#getObject 方法用于生成mapper的代理类       
      definition.setBeanClass(this.mapperFactoryBean.getClass());

     // 注册了 sqlSessionFactory
	 if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) {
	        definition.getPropertyValues().add("sqlSessionFactory", 
	                    new RuntimeBeanReference(this.sqlSessionFactoryBeanName));
	        explicitFactoryUsed = true;
	      }
 }

注意
@Autowired 在注入 UserMapper 实例时,会将 MapperFactoryBean#getObject 方法返回的实例注入

 @Autowired
 private UserMapper userMapper;

上面注册了MapperFactoryBean类,查看该类
查看父类,发现 org.mybatis.spring.support.SqlSessionDaoSupport

  // 会调用该方法,将配置的 sqlSessionFactory 对象传入进来
  public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
    if (!this.externalSqlSession) {
      // sqlSession 是 mybatis 的顶层接口,于数据库交换的对象,查看该类
      this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
    }
  }

org.mybatis.spring.SqlSessionTemplate#SqlSessionTemplate(org.apache.ibatis.session.SqlSessionFactory, org.apache.ibatis.session.ExecutorType, org.springframework.dao.support.PersistenceExceptionTranslator)

//对 sqlSession 产生代理(jdk代理)
 this.sqlSessionProxy = (SqlSession) newProxyInstance(
        SqlSessionFactory.class.getClassLoader(),
        new Class[] { SqlSession.class },
        new SqlSessionInterceptor());

mapper 的代理类生成

查看
org.mybatis.spring.mapper.MapperFactoryBean#getObject
对mapper的接口类产生代理类

 @Override
  public T getObject() throws Exception {
    // 进入 SqlSessionTemplate
    return getSqlSession().getMapper(this.mapperInterface);
  }

org.mybatis.spring.SqlSessionTemplate#getMapper

  @Override
  public <T> T getMapper(Class<T> type) {
    return getConfiguration().getMapper(type, this);
  }

org.apache.ibatis.session.Configuration#getMapper

 public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    return mapperRegistry.getMapper(type, sqlSession);
  }

org.apache.ibatis.binding.MapperRegistry#getMapper

// knownMappers 容器是在解析 mapper xml时初始化的
// type 就是 mapper 的接口类
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);

// MapperProxyFactory类 实例化
// sqlSession 就是 SqlSessionTemplate
return mapperProxyFactory.newInstance(sqlSession);

org.apache.ibatis.binding.MapperProxyFactory#newInstance(org.apache.ibatis.session.SqlSession)

 public T newInstance(SqlSession sqlSession) {
    final MapperProxy<T> mapperProxy = 
               new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
    return newInstance(mapperProxy);
  }

// 产生jdk代理类
// mapperInterface 是 mapper的接口类
// mapperProxy 是代理通知实现类,即实现 InvocationHandler 接口
protected T newInstance(MapperProxy<T> mapperProxy) {
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }

可以看出在依赖注入 mapper接口时,其实注入的是MapperProxy ,即mapper的代理类,
调用 mapper 接口方法时,会调用到 org.apache.ibatis.binding.MapperProxy#invoke

查看
org.apache.ibatis.binding.MapperProxy#invoke

final MapperMethod mapperMethod = cachedMapperMethod(method);

org.apache.ibatis.binding.MapperProxy#cachedMapperMethod

    MapperMethod mapperMethod = methodCache.get(method);
    if (mapperMethod == null) {
      //查看 MapperMethod
      mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());
      methodCache.put(method, mapperMethod);
    }

org.apache.ibatis.binding.MapperMethod#MapperMethod

   this.command = new SqlCommand(config, mapperInterface, method);
    this.method = new MethodSignature(config, mapperInterface, method);

SqlCommand
org.apache.ibatis.binding.MapperMethod.SqlCommand#SqlCommand

 final String methodName = method.getName();
 final Class<?> declaringClass = method.getDeclaringClass();
 //根据方法名找到 MappedStatement 对象,MappedStatement 对象是在解析 mapper xml时初始化的
 // MappedStatement 中的 sqlSource 就是 执行sql的信息
 MappedStatement ms = resolveMappedStatement(mapperInterface, methodName, 
 		declaringClass,configuration);

返回到
org.apache.ibatis.binding.MapperMethod#MapperMethod

 this.command = new SqlCommand(config, mapperInterface, method);
  // 查看该方法
  this.method = new MethodSignature(config, mapperInterface, method);

org.apache.ibatis.binding.MapperMethod.MethodSignature#MethodSignature

// 获取 mapper 方法的返回值类型
 Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, mapperInterface);
 
 //判断返回类型是否是 void
 this.returnsVoid = void.class.equals(this.returnType);
 //判断返回类型是否是 集合
 this.returnsMany = (configuration.getObjectFactory().isCollection(this.returnType) ||  
     this.returnType.isArray());
 this.returnsCursor = Cursor.class.equals(this.returnType);
 //判断方法参数上为 RowBounds 类型的是第几个,即参数的索引
 this.rowBoundsIndex = getUniqueParamIndex(method, RowBounds.class);
 ///判断方法参数上为 ResultHandler类型的是第几个,即参数的索引
 this.resultHandlerIndex = getUniqueParamIndex(method, ResultHandler.class);

mapper接口方法的执行

返回到
org.apache.ibatis.binding.MapperProxy#invoke
mapper 接口中的方法真正执行

return mapperMethod.execute(sqlSession, args);

org.apache.ibatis.binding.MapperMethod#execute

    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:
        //当前sql为查询时
        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);
        }
        break;
      case FLUSH:
        result = sqlSession.flushStatements();
        break;
      default:
        throw new BindingException("Unknown execution method for: " + command.getName());
    }

org.mybatis.spring.SqlSessionTemplate#selectOne(java.lang.String, java.lang.Object)

  @Override
  public <T> T selectOne(String statement, Object parameter) {
    return this.sqlSessionProxy.<T> selectOne(statement, parameter);
  }

通过上面分析,得知 sqlSession 会有一个代理类,即 SqlSessionInterceptor,所以调用sqlSession方法时会进入到代理类 SqlSessionInterceptor#invoke

查看sqlSession 代理通知类
org.apache.ibatis.session.SqlSessionManager.SqlSessionInterceptor#invoke

@Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      //获取 sqlSession
      SqlSession sqlSession = getSqlSession(
          SqlSessionTemplate.this.sqlSessionFactory,
          SqlSessionTemplate.this.executorType,
          SqlSessionTemplate.this.exceptionTranslator);
      try {
        //SqlSession中方法执行的结果
        Object result = method.invoke(sqlSession, args);
        if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
          sqlSession.commit(true);
        }
        return result;
      } catch (Throwable t) {
        Throwable unwrapped = unwrapThrowable(t);
        throw unwrapped;
      } finally {
        if (sqlSession != null) {
          closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
        }
      }
    }

org.mybatis.spring.SqlSessionUtils#getSqlSession(org.apache.ibatis.session.SqlSessionFactory, org.apache.ibatis.session.ExecutorType, org.springframework.dao.support.PersistenceExceptionTranslator)

  session = sessionFactory.openSession(executorType);

org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSession(org.apache.ibatis.session.ExecutorType)

return openSessionFromDataSource(execType, null, false);

org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSessionFromDataSource

// Executor :mybatis执行器,负责Sql的生成和查询
final Executor executor = configuration.newExecutor(tx, execType);
return new DefaultSqlSession(configuration, executor, autoCommit);

org.apache.ibatis.session.Configuration#newExecutor(org.apache.ibatis.transaction.Transaction, org.apache.ibatis.session.ExecutorType)

public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
    executorType = executorType == null ? defaultExecutorType : executorType;
    executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
    Executor executor;
    if (ExecutorType.BATCH == executorType) {
      executor = new BatchExecutor(this, transaction);
    } else if (ExecutorType.REUSE == executorType) {
      executor = new ReuseExecutor(this, transaction);
    } else {
    //默认使用这个
      executor = new SimpleExecutor(this, transaction);
    }
    if (cacheEnabled) {
      executor = new CachingExecutor(executor);
    }
    // mybatis 插件执行,即sql拦截器
    executor = (Executor) interceptorChain.pluginAll(executor);
    return executor;
  }

mybatis 插件 在 mybatis的全局配置文件中配置

返回到
org.mybatis.spring.SqlSessionTemplate.SqlSessionInterceptor#invoke

// SqlSession中方法执行的结果,SqlSession 对象是 DefaultSqlSession
Object result = method.invoke(sqlSession, args);

例如DefaultSqlSession#selectOne 方法执行
org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)

 @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.<T>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;
    }
  }

  @Override
  public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
    try {
    // statement 是mapper xml定义的mapper的命名空间加方法的字符串
    // 每个方法都会封装成 MappedStatement 对象
      MappedStatement ms = configuration.getMappedStatement(statement);
      //mybatis执行器操作,如果配置有mybatis的插件时,则会进入到配置的插件中
      // 查看 query 方法,见下
      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();
    }
  }

wrapCollection(parameter) 查数包装
从这里可以看出,在使有 foreach 标签时,默认 collection 元素值 使用这里定义的别名中取值

private Object wrapCollection(final Object object) {
    if (object instanceof Collection) {
      StrictMap<Object> map = new StrictMap<Object>();
      map.put("collection", object);
      if (object instanceof List) {
        map.put("list", object);
      }
      return map;
    } else if (object != null && object.getClass().isArray()) {
      StrictMap<Object> map = new StrictMap<Object>();
      map.put("array", object);
      return map;
    }
    return object;
  }

org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)

  @Override
  public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
    //查看 getBoundSql,分析:DynamicSqlSource
    BoundSql boundSql = ms.getBoundSql(parameterObject);
    CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
    return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
  }

org.apache.ibatis.scripting.xmltags.DynamicSqlSource#getBoundSql

   DynamicContext context = new DynamicContext(configuration, parameterObject);
    //例如,调到 IfSqlNode#apply
    // 执行完下面的方法 apply,此时 DynamicContext#sqlBuilder 中会有一个完整的sql,
    // 这个sql就是动态生成后的,最终需要执行的sql语句
    // 例如sqlBuilder中的最终sql:  SELECT * from t_user WHERE id=#{id} 
    rootSqlNode.apply(context);

IfSqlNode#apply
org.apache.ibatis.scripting.xmltags.IfSqlNode#apply

  @Override
  public boolean apply(DynamicContext context) {
    // 判断 test 中的表达式是否成立
    // test: 表达式字符串
    // context.getBindings() mapper方法的参数信息
    if (evaluator.evaluateBoolean(test, context.getBindings())) {
      //成立时,则迭代下一个,因为动态标签中可能有多个sqlNode
      contents.apply(context);
      return true;
    }
    return false;
  }

返回到
org.apache.ibatis.scripting.xmltags.DynamicSqlSource#getBoundSql

  @Override
  public BoundSql getBoundSql(Object parameterObject) {
    DynamicContext context = new DynamicContext(configuration, parameterObject);
    rootSqlNode.apply(context);
    //上面已将动态的sql解析成 需要执行的sql,但是还未解析 例如:#{id} 这样的格式
    SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
    Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();
    // 解析 #{} 的格式,查看 parse 方法
    SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings());
    BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
    for (Map.Entry<String, Object> entry : context.getBindings().entrySet()) {
      boundSql.setAdditionalParameter(entry.getKey(), entry.getValue());
    }
    return boundSql;
  }

org.apache.ibatis.builder.SqlSourceBuilder#parse

  public SqlSource parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameters) {
    ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(configuration, parameterType, additionalParameters);
    GenericTokenParser parser = new GenericTokenParser("#{", "}", handler);
    // 将sql中的 #{} 变为了 ?
    // 例如:SELECT * from t_user  WHERE id=?
    String sql = parser.parse(originalSql);
    return new StaticSqlSource(configuration, sql, handler.getParameterMappings());
  }

查看 parser.parse(originalSql) 方法,其中 handler.handleToken(expression.toString())会用调用到
org.apache.ibatis.builder.SqlSourceBuilder.ParameterMappingTokenHandler#handleToken会返回一个 ? 字符。
为什么将 #{} 变为了 ?,因为jdbc要预编译,预编译必须要用?做为占位符

org.apache.ibatis.builder.SqlSourceBuilder.ParameterMappingTokenHandler#handleToken

   @Override
    public String handleToken(String content) {
    // 查看 buildParameterMapping 方法
      parameterMappings.add(buildParameterMapping(content));
      return "?";
    }

org.apache.ibatis.builder.SqlSourceBuilder.ParameterMappingTokenHandler#buildParameterMapping


 Map<String, String> propertiesMap = parseParameterMapping(content);
  String property = propertiesMap.get("property");

      for (Map.Entry<String, String> entry : propertiesMap.entrySet()) {
        String name = entry.getKey();
        String value = entry.getValue();
       if ("javaType".equals(name)) {
          javaType = resolveClass(value);
          builder.javaType(javaType);
        } else if ("jdbcType".equals(name)) {
          builder.jdbcType(resolveJdbcType(value));
        } else if ("mode".equals(name)) {
          builder.mode(resolveParameterMode(value));
        } else if ("numericScale".equals(name)) {
          builder.numericScale(Integer.valueOf(value));
        } else if ("resultMap".equals(name)) {
          builder.resultMapId(value);
        } else if ("typeHandler".equals(name)) {
          typeHandlerAlias = value;
        } else if ("jdbcTypeName".equals(name)) {
          builder.jdbcTypeName(value);
        } else if ("property".equals(name)) {
          // Do Nothing
        } else if ("expression".equals(name)) {
          throw new BuilderException("Expression based parameters are not supported yet");
        } else {
          throw new BuilderException("An invalid property '" + name + "' was found in mapping #{" + content + "}.  Valid properties are " + parameterProperties);
        }
      }

返回到
org.apache.ibatis.scripting.xmltags.DynamicSqlSource#getBoundSql

SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, 	
		 context.getBindings());
BoundSql boundSql = sqlSource.getBoundSql(parameterObject);

BoundSql 类中的属性

  • sql
    被 执行的sql ,例如 SELECT * from t_user WHERE id=?
  • parameterObject
    被 执行的sql的入参信息

返回到
org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)

  @Override
  public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
    //上面已解析
    BoundSql boundSql = ms.getBoundSql(parameterObject);
    CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
    //查看该方法
    return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
  }

org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

 return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);

org.apache.ibatis.executor.BaseExecutor#query

list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);

org.apache.ibatis.executor.BaseExecutor#queryFromDatabase

 list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);

org.apache.ibatis.executor.SimpleExecutor#doQuery

 Configuration configuration = ms.getConfiguration();
      // newStatementHandler 这里有mybatis的拦截器的入口 
      StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
      stmt = prepareStatement(handler, ms.getStatementLog());
      return handler.<E>query(stmt, resultHandler);

org.apache.ibatis.session.Configuration#newStatementHandler

  // 查看 RoutingStatementHandler
  StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
    statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
    return statementHandler;

org.apache.ibatis.executor.statement.RoutingStatementHandler#RoutingStatementHandler

    switch (ms.getStatementType()) {
      case STATEMENT:
        delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
        break;
      case PREPARED:
        //预编译类型,会走到这里,查看 PreparedStatementHandler
        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());
    }

查看 PreparedStatementHandler 的父类
org.apache.ibatis.executor.statement.BaseStatementHandler#BaseStatementHandler

// 返回代理对象,负责对用户传递的参数转换成 Jdbc statement 所需要的参数
  this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
// 返回代理对象,jdbc 返回的 ResultSet结果集转成List类的集合  
    this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);

返回到
org.apache.ibatis.executor.SimpleExecutor#doQuery

 stmt = prepareStatement(handler, ms.getStatementLog());

org.apache.ibatis.executor.SimpleExecutor#prepareStatement

private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
    Statement stmt;
    //这里获取的是Connection 的代理对象
    Connection connection = getConnection(statementLog);
    //初始化 Statement 对象
    stmt = handler.prepare(connection, transaction.getTimeout());
    //设置预编译参数的值,即设置占位符的参数值
    handler.parameterize(stmt);
    return stmt;
  }

org.apache.ibatis.type.TypeHandlerRegistry类中注册了 javaType 和 JdbcType的类型处理器,根据传参的参数类型获取对应的处理器

org.apache.ibatis.executor.statement.BaseStatementHandler#prepare

     //查看该方法
     statement = instantiateStatement(connection);
      setStatementTimeout(statement, transactionTimeout);
      setFetchSize(statement);
      return statement;

org.apache.ibatis.executor.statement.PreparedStatementHandler#instantiateStatement

@Override
  protected Statement instantiateStatement(Connection connection) throws SQLException {
    String sql = boundSql.getSql();
    if (mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) {
      String[] keyColumnNames = mappedStatement.getKeyColumns();
      if (keyColumnNames == null) {
        return connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
      } else {
        return connection.prepareStatement(sql, keyColumnNames);
      }
    } else if (mappedStatement.getResultSetType() != null) {
      return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
    } else {
       //调用这个方法时,会进入到代理对象类中,connection对象其实是个代理
      return connection.prepareStatement(sql);
    }
  }

org.apache.ibatis.logging.jdbc.ConnectionLogger#invoke

if (Object.class.equals(method.getDeclaringClass())) {
        return method.invoke(this, params);
      }    
      if ("prepareStatement".equals(method.getName())) {
        if (isDebugEnabled()) {
          debug(" Preparing: " + removeBreakingWhitespace((String) params[0]), true);
        }        
        PreparedStatement stmt = (PreparedStatement) method.invoke(connection, params);
        // 对PreparedStatement  进行代理
        stmt = PreparedStatementLogger.newInstance(stmt, statementLog, queryStack);
        return stmt;
      } else if ("prepareCall".equals(method.getName())) {
        if (isDebugEnabled()) {
          debug(" Preparing: " + removeBreakingWhitespace((String) params[0]), true);
        }        
        PreparedStatement stmt = (PreparedStatement) method.invoke(connection, params);
        stmt = PreparedStatementLogger.newInstance(stmt, statementLog, queryStack);
        return stmt;
      } else if ("createStatement".equals(method.getName())) {
        Statement stmt = (Statement) method.invoke(connection, params);
        stmt = StatementLogger.newInstance(stmt, statementLog, queryStack);
        return stmt;
      } else {
        return method.invoke(connection, params);
      }

返回到
org.apache.ibatis.executor.SimpleExecutor#prepareStatement

   //stmt 就是一个代理对象,见上面解析
   stmt = handler.prepare(connection, transaction.getTimeout());
    //设置参数,内部方法:typeHandler.setParameter(ps, i + 1, value, jdbcType);
    handler.parameterize(stmt);

Statement 设置值时,会 stmt.setString(设置sql中?的参数的索引,参数值)

返回到
org.apache.ibatis.executor.SimpleExecutor#doQuery

stmt = prepareStatement(handler, ms.getStatementLog());
//查看该方法
return handler.<E>query(stmt, resultHandler);

org.apache.ibatis.executor.statement.PreparedStatementHandler#query

  @Override
  public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
    PreparedStatement ps = (PreparedStatement) statement;
    //sql真正的执行
    ps.execute();
    // sql结果集的处理
    return resultSetHandler.<E> handleResultSets(ps);
  }

sql执行结果的返回封装

org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleResultSets

 int resultSetCount = 0;
 //查看该方法
ResultSetWrapper rsw = getFirstResultSet(stmt);
int resultMapCount = resultMaps.size();
List<ResultMap> resultMaps = mappedStatement.getResultMaps();
  while (rsw != null && resultMapCount > resultSetCount) {
      ResultMap resultMap = resultMaps.get(resultSetCount);
       // 对sql的结果集进行处理
      handleResultSet(rsw, resultMap, multipleResults, null);
      rsw = getNextResultSet(stmt);
      cleanUpAfterHandlingResultSet();
      resultSetCount++;
    }

getFirstResultSet

private ResultSetWrapper getFirstResultSet(Statement stmt) throws SQLException {
    //获取sql执行的结果集
    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;
        }
      }
    }
     // 查看该方法 ResultSetWrapper
    return rs != null ? new ResultSetWrapper(rs, configuration) : null;
  }

org.apache.ibatis.executor.resultset.ResultSetWrapper#ResultSetWrapper

public ResultSetWrapper(ResultSet rs, Configuration configuration) throws SQLException {
    super();
    // 从配置中获取 类型转换器
    this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
    this.resultSet = rs;
    // sql执行后的元信息,
    final ResultSetMetaData metaData = rs.getMetaData();
    final int columnCount = metaData.getColumnCount();
    for (int i = 1; i <= columnCount; i++) {
      columnNames.add(configuration.isUseColumnLabel() ? metaData.getColumnLabel(i) : metaData.getColumnName(i));
      //每一列的类型
      jdbcTypes.add(JdbcType.forCode(metaData.getColumnType(i)));
      classNames.add(metaData.getColumnClassName(i));
    }
  }

handleResultSet
org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleResultSet

       if (resultHandler == null) {
          DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);
           //查看该方法
          handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);
          multipleResults.add(defaultResultHandler.getResultList());
        }

org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleRowValues

 handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);

org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleRowValuesForSimpleResultMap

// 跳过分页
 skipRows(rsw.getResultSet(), rowBounds);
 // rsw.getResultSet().next() 循环每一行的记录
  while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
        //循环每一行,封装每一行的值到对象中
		Object rowValue = getRowValue(rsw, discriminatedResultMap);
  }

 

RowBounds 逻辑分页,一般不用 offset 从哪一个记录开始, limit 查询出记录的个数

org.apache.ibatis.executor.resultset.DefaultResultSetHandler#getRowValue(org.apache.ibatis.executor.resultset.ResultSetWrapper, org.apache.ibatis.mapping.ResultMap)

// 创建一个要返回的空对象
 Object rowValue = createResultObject(rsw, resultMap, lazyLoader, null);
 
 foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, null) || foundValues;

org.apache.ibatis.executor.resultset.DefaultResultSetHandler#applyPropertyMappings

  // 这个就是mapper xml中的 resultMap
  final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();
      for (ResultMapping propertyMapping : propertyMappings) {
       //mapper xml中的 resultMap中的每一行处理,也就是每一列的处理
       Object value = getPropertyMappingValue(rsw.getResultSet(), metaObject, propertyMapping, lazyLoader, columnPrefix);

// 将值设置到上面创建的空对象中
 metaObject.setValue(property, value);
      }

getPropertyMappingValue
org.apache.ibatis.executor.resultset.DefaultResultSetHandler#getPropertyMappingValue

// 类型
 final TypeHandler<?> typeHandler = propertyMapping.getTypeHandler();
// 根据列名获取值
 return typeHandler.getResult(rs, column);

org.apache.ibatis.type.BaseTypeHandler#getResult(java.sql.ResultSet, java.lang.String)

result = getNullableResult(rs, columnName);

根据相应的类型处理器处理值
在这里插入图片描述

返回到
org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleRowValuesForSimpleResultMap

Object rowValue = getRowValue(rsw, discriminatedResultMap);
storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());

org.apache.ibatis.executor.resultset.DefaultResultSetHandler#storeObject

callResultHandler(resultHandler, resultContext, rowValue);

org.apache.ibatis.executor.resultset.DefaultResultSetHandler#callResultHandler

  private void callResultHandler(ResultHandler<?> resultHandler, DefaultResultContext<Object> resultContext, Object rowValue) {
    resultContext.nextResultObject(rowValue);
     //查看 handleResult 方法
    ((ResultHandler<Object>) resultHandler).handleResult(resultContext);
  }

org.apache.ibatis.executor.result.DefaultResultHandler#handleResult
将封装的结果对象添加到list中

@Override
  public void handleResult(ResultContext<? extends Object> context) {
    list.add(context.getResultObject());
  }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章