SEARU.ORG
当前位置:SEARU.ORG > Linux 新闻 > 正文

MyBatis 一句sql的执行流程

待日后有所提高之后在进行修正更新 2016年03月12日

在上一会MyBatis解析自身配置文件记录中我们简单了解了一下框架解析配置信息的流程,下面我们看看一句sql是怎么执行的;

项目代码还是以官方的mybatis-3-mybatis-3.3.0项目为基础

  • 入口:
    public class SqlSessionTest extends BaseDataTest {
      private static SqlSessionFactory sqlMapper;
    
      @BeforeClass
      public static void setup() throws Exception {
        createBlogDataSource();
        final String resource = "org/apache/ibatis/builder/MapperConfig.xml";
        final Reader reader = Resources.getResourceAsReader(resource);
        sqlMapper = new SqlSessionFactoryBuilder().build(reader);
      }  
      
      @Test
      public void shouldSelectAllAuthors() throws Exception {
        SqlSession session = sqlMapper.openSession(TransactionIsolationLevel.SERIALIZABLE);
        try {
          List<Author> authors = session.selectList("org.apache.ibatis.domain.blog.mappers.AuthorMapper.selectAllAuthors");
          assertEquals(2, authors.size());
        } finally {
          session.close();
        }
  }

待执行的sql:

    <select id="selectAllAuthors" resultType="org.apache.ibatis.domain.blog.Author">
        select * from author
    </select>
  • 第一步我们先看看SqlSessionFactory sqlMapper;用的是:
    package org.apache.ibatis.session;
    public class SqlSessionFactoryBuilder {
    
     public SqlSessionFactory build(Configuration config) {
        return new DefaultSqlSessionFactory(config);//实现
      }

    package org.apache.ibatis.session.defaults;
    public class DefaultSqlSessionFactory implements SqlSessionFactory {

      private final Configuration configuration;

      public DefaultSqlSessionFactory(Configuration configuration) {
        this.configuration = configuration;
      }
  • SqlSessions

    SqlSessions are created by a SqlSessionFactory instance. The SqlSessionFactory contains methods for creating instances of SqlSessions all different ways. The SqlSessionFactory itself is created by the SqlSessionFactoryBuilder that can create the SqlSessonFactory from XML, Annotations or hand coded Java configuration.

    NOTE When using MyBatis with a dependency injection framework like Spring or Guice, SqlSessions are created and injected by the DI framework so you don't need to use the SqlSessionFactoryBuilder or SqlSessionFactory and can go directly to the SqlSession section. Please refer to the MyBatis-Spring or MyBatis-Guice manuals for further info.

    • 之后看看session是怎么获取到的:SqlSession session = sqlMapper.openSession(TransactionIsolationLevel.SERIALIZABLE);,调的是SqlSession openSession(TransactionIsolationLevel level);接口:

      具体的事务级别:

      MyBatis uses a Java enumeration wrapper for transaction isolation levels, called TransactionIsolationLevel, but otherwise they work as expected and have the 5 levels supported by JDBC (NONE, READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE).

            int TRANSACTION_SERIALIZABLE     = 8;
    
    • DefaultSqlSessionFactory实现
    @Override
    public SqlSession openSession(TransactionIsolationLevel level) {
    //这里看到我们上一篇说过的很重要的configuration出现了,我们要拿东西了(看看方法名称基本就不想看了吧:)),注意我们这里的level是SERIALIZABLE(Connection.TRANSACTION_SERIALIZABLE);->8级别,而配置对象中ExecutorType是?
    //ExecutorType.SIMPLE -> 0
    //ExecutorType.SIMPLE: This type of executor does nothing special. It creates a new PreparedStatement for each execution of a statement.
    //false 标识不自动提交(autoCommit)
    return openSessionFromDataSource(configuration.getDefaultExecutorType(), level, false);
    }
    
    private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
    try {
      final Environment environment = configuration.getEnvironment();//Environment determines which environment to load, including the datasource and transaction manager.
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);//得到的是org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory,environment.getTransactionFactory()中的对象
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);// Creates a {@link Transaction} out of a datasource.
      //dataSource:环境中存储的是包裹了org.apache.derby.jdbc.EmbeddedDriver驱动的的org.apache.ibatis.datasource.unpooled.UnpooledDataSource实现,得到一个org.apache.ibatis.transaction.jdbc.JdbcTransaction
      final Executor executor = configuration.newExecutor(tx, execType);//新建一个框架自身的org.apache.ibatis.executor.Executor,实现executor = new SimpleExecutor(this, transaction);,框架的executor定义了我们可以执行的sql方法,比如update、query等;其下将会保持:
      /*
        public abstract class BaseExecutor implements Executor {
    
    private static final Log log = LogFactory.getLog(BaseExecutor.class);
    
    protected Transaction transaction;
    protected Executor wrapper;
    
    protected ConcurrentLinkedQueue<DeferredLoad> deferredLoads;
    protected PerpetualCache localCache;
    protected PerpetualCache localOutputParameterCache;
    protected Configuration configuration;
    
    protected int queryStack = 0;
    private boolean closed;
    
    protected BaseExecutor(Configuration configuration, Transaction transaction) {
    this.transaction = transaction; 一个org.apache.ibatis.transaction.jdbc.JdbcTransaction事务对象
    this.deferredLoads = new ConcurrentLinkedQueue<DeferredLoad>();
    this.localCache = new PerpetualCache("LocalCache");
    this.localOutputParameterCache = new PerpetualCache("LocalOutputParameterCache");
    this.closed = false;
    this.configuration = configuration; 全局配置对象
    this.wrapper = this;
    }
    
    因为我们主配置文件中设置了<setting name="cacheEnabled" value="true"/>,那么SimpleExecutor还会被封装成:
    if (cacheEnabled) {
      executor = new CachingExecutor(executor); 包裹器
    }
    executor = (Executor) interceptorChain.pluginAll(executor); 这行代码很关键,将会把这个可执行对象放入我们的插件拦截器中,即调用Object plugin(Object target)接口,如果我们配置了拦截器,这里可能还要被代理包裹一层,返回持有executor的动态代理对象
    return executor;
    }
    
    Executor 接口:
    public interface Executor {
    
          ResultHandler NO_RESULT_HANDLER = null;
    
          int update(MappedStatement ms, Object parameter) throws SQLException;
    
          <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException;
    
          <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException;
    
          List<BatchResult> flushStatements() throws SQLException;
    
          void commit(boolean required) throws SQLException;
    
          void rollback(boolean required) throws SQLException;
    
          CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql);
    
          boolean isCached(MappedStatement ms, CacheKey key);
    
          void clearLocalCache();
    
          void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType);
    
          Transaction getTransaction();
    
          void close(boolean forceRollback);
    
          boolean isClosed();
    
          void setExecutorWrapper(Executor executor);
    
        }
      */
    
      return new DefaultSqlSession(configuration, executor, autoCommit);//得到executor之后,就创建实际的session对象
      /*
          public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
        this.configuration = configuration; 全局配置对象
        this.executor = executor; 
        this.dirty = false;
        this.autoCommit = autoCommit;
      }
    
      */
    } catch (Exception e) {
      closeTransaction(tx); // may have fetched a connection so lets call close()
      throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
    }
    
  • 执行<E> List<E> selectList(String statement);接口:

    List<Author> authors = session.selectList("org.apache.ibatis.domain.blog.mappers.AuthorMapper.selectAllAuthors");

        <select id="selectAllAuthors" resultType="org.apache.ibatis.domain.blog.Author">
            select * from author
        </select>
    
    public class Author implements Serializable {
    
      protected int id;
      protected String username;
      protected String password;
      protected String email;
      protected String bio;
      protected Section favouriteSection;
    
    
        /**
       * Retrieve a list of mapped objects from the statement key and parameter.
       * @param <E> the returned list element type
       * @param statement Unique identifier matching the statement to use.
       * @return List of mapped object
       */
      <E> List<E> selectList(String statement);
    
      //实际调用:
      @Override
      public <E> List<E> selectList(String statement) {
        return this.selectList(statement, null);
      }
    
       @Override
      public <E> List<E> selectList(String statement, Object parameter) {
        return this.selectList(statement, parameter, RowBounds.DEFAULT);//--》  public static final RowBounds DEFAULT = new RowBounds();
      }
    
       @Override
      public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
        try {
        /*
            通过org.apache.ibatis.domain.blog.mappers.AuthorMapper.selectAllAuthors作为id去获取MappedStatement,这个id是怎么拼出来的好像我们似成相识,可以回忆一下上一篇中:关于「解析sql语句」一节:
            //下面这部检查会将id重新赋值为命名空间加id的形式
    if (!databaseIdMatchesCurrent(id, databaseId, this.requiredDatabaseId)) {
    return;
    }
        */
          MappedStatement ms = configuration.getMappedStatement(statement);
          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();
        }
      }
    
    
  • 查看mybatis如何从配置对象中获取我们要执行的sql:MappedStatement

    public MappedStatement getMappedStatement(String id) {
    return this.getMappedStatement(id, true);
    }
    
    public MappedStatement getMappedStatement(String id, boolean validateIncompleteStatements) {
    if (validateIncompleteStatements) {
      buildAllStatements();
    }
    return mappedStatements.get(id);
    }
    

protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection");

得到的sql模型对象:

        public final class MappedStatement {

          private String resource;//语句所在的mapper的配置信息:org/apache/ibatis/builder/AuthorMapper.xml
          private Configuration configuration;//全局配置对象
          private String id;//解析mapper之后对应<select id="selectAllAuthorsLinkedList"标识符
          private Integer fetchSize;
          private Integer timeout;
          private StatementType statementType;//statementType is a type of the statement that is any one of STATEMENT, PREPARED or CALLABLE that is mapped to Statement, PreparedStatement and CallableStatement respectively. The default is PREPARED.
          private ResultSetType resultSetType;
          private SqlSource sqlSource;//将sql和参数集合封装成模型对象StaticSqlSource:其中sql即select * from author
          private Cache cache;
          private ParameterMap parameterMap;//执行sql所需的参数模型对象
          private List<ResultMap> resultMaps;//resultType="org.apache.ibatis.domain.blog.Author"或者resultMap="selectComplexImmutableAuthor"的模型,其中private Class<?> type;来存储resultType对应的clazz类型
          private boolean flushCacheRequired;
          private boolean useCache;
          private boolean resultOrdered;
          private SqlCommandType sqlCommandType;//标识当前sql的类型:SqlCommandType {  UNKNOWN, INSERT, UPDATE, DELETE, SELECT, FLUSH;
          private KeyGenerator keyGenerator;
          private String[] keyProperties;
          private String[] keyColumns;
          private boolean hasNestedResultMaps;
          private String databaseId;
          private Log statementLog;//日志对象,如org.slf4j.impl.Log4jLoggerAdapter(org.apache.ibatis.domain.blog.mappers.AuthorMapper.selectAllAuthors)
          private LanguageDriver lang;
          private String[] resultSets;
    
  • 执行查询:executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);

    
    @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);
    }
    
    public BoundSql getBoundSql(Object parameterObject) {
    BoundSql boundSql = sqlSource.getBoundSql(parameterObject);//将真实的参数和sqlSource中的数据重新用另一个模型封装
    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
    if (parameterMappings == null || parameterMappings.isEmpty()) {
      boundSql = new BoundSql(configuration, boundSql.getSql(), parameterMap.getParameterMappings(), parameterObject);
    }
    
    // check for nested result maps in parameter mappings (issue #30)
    for (ParameterMapping pm : boundSql.getParameterMappings()) {
      String rmId = pm.getResultMapId();
      if (rmId != null) {
        ResultMap rm = configuration.getResultMap(rmId);
        if (rm != null) {
          hasNestedResultMaps |= rm.hasNestedResultMaps();
        }
      }
    }
    
    //省略一些基础嵌套...
    
    list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
    
     @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();
      //关键:创建jdbc statement,这个RoutingStatementHandler将用于封装PreparedStatementHandler,PreparedStatementHandler用来真正的帮助我们完成sql的执行,比如查询:
    //       PreparedStatement ps = (PreparedStatement) statement;
    //       ps.execute();
    //作为executor下的一个执行代理:
    ![](media/14575989286827/14577878384594.jpg)
    //其中还存储了用于处理参数的parameterHandler和处理结果的resultSetHandler
      StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
      stmt = prepareStatement(handler, ms.getStatementLog());//创建statment
      return handler.<E>query(stmt, resultHandler);//执行sql
    } finally {
      closeStatement(stmt);
    }
    }
    
    public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
    StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
    statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
    return statementHandler;
    }
    
    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://故我们将会用jdbc的PreparedStatement
        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());
    }
    
    }
    
    public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
    ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql);
    parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler);//再次调用插件链,我们插件的生命周期3循环调用插件的target = interceptor.plugin(target);方法,传递的对象DefaultParameterHandler
    ![](media/14575989286827/14577855844795.jpg)
    
    return parameterHandler;
    }
    
    
    • 创建statement:stmt = prepareStatement(handler, ms.getStatementLog());
    private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
    Statement stmt;
    Connection connection = getConnection(statementLog);
    stmt = handler.prepare(connection);////实际创建Statement
    handler.parameterize(stmt);//设置参数
    return stmt;
    }
    
    //获取数据库连接Connection对象
    protected Connection getConnection(Log statementLog) throws SQLException {
    Connection connection = transaction.getConnection();//从JdbcTransaction中查看connection成员变量有没有被初始化了,如果没有就通过内部持有的connection = dataSource.getConnection();()
    if (statementLog.isDebugEnabled()) {
      return ConnectionLogger.newInstance(connection, statementLog, queryStack);
    } else {
      return connection;
    }
    }
    
    //实际创建Statement的方法,在PreparedStatementHandler中完成
    @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 {
      return connection.prepareStatement(sql);
    }
    }
    
    //设置参数:调用PreparedStatementHandler持有的DefaultParameterHandler完成
    @Override
    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) {
          Object value;
          String propertyName = parameterMapping.getProperty();
          if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
            value = boundSql.getAdditionalParameter(propertyName);
          } else if (parameterObject == null) {
            value = null;
          } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
            value = parameterObject;
          } else {
            MetaObject metaObject = configuration.newMetaObject(parameterObject);
            value = metaObject.getValue(propertyName);
          }
          TypeHandler typeHandler = parameterMapping.getTypeHandler();
          JdbcType jdbcType = parameterMapping.getJdbcType();
          if (value == null && jdbcType == null) {
            jdbcType = configuration.getJdbcTypeForNull();
          }
          try {
            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);
          }
        }
      }
    }
    }
    
    • 执行sql查询:return handler.<E>query(stmt, resultHandler);
     @Override
    public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
        PreparedStatement ps = (PreparedStatement) statement;
        ps.execute();
        return resultSetHandler.<E> handleResultSets(ps);//进行结果映射
    }
    
    • 结果映射
    @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);
      handleResultSet(rsw, resultMap, multipleResults, null);
      rsw = getNextResultSet(stmt);
      cleanUpAfterHandlingResultSet();
      resultSetCount++;
    }
    
    String[] resultSets = mappedStatement.getResulSets();
    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);
    }
    
    private ResultSetWrapper getFirstResultSet(Statement stmt) throws SQLException {
    ResultSet rs = stmt.getResultSet();//获取ResultSet
    //   ...
    return rs != null ? new ResultSetWrapper(rs, configuration) : null;
    }
    
    class ResultSetWrapper {
    
    private final ResultSet resultSet;
    private final TypeHandlerRegistry typeHandlerRegistry;
    private final List<String> columnNames = new ArrayList<String>();//columnNames
    private final List<String> classNames = new ArrayList<String>();//每个字段对应的java类型集合
    private final List<JdbcType> jdbcTypes = new ArrayList<JdbcType>();//每个字段对应的jdbc类型集合
    private final Map<String, Map<Class<?>, TypeHandler<?>>> typeHandlerMap = new HashMap<String, Map<Class<?>, TypeHandler<?>>>();
    private Map<String, List<String>> mappedColumnNamesMap = new HashMap<String, List<String>>();
    private Map<String, List<String>> unMappedColumnNamesMap = new HashMap<String, List<String>>();
    
    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.add(configuration.isUseColumnLabel() ? metaData.getColumnLabel(i) : metaData.getColumnName(i));
      jdbcTypes.add(JdbcType.forCode(metaData.getColumnType(i)));
      classNames.add(metaData.getColumnClassName(i));
    }
    }
    
    //省略...
    Object rowValue = getRowValue(rsw, discriminatedResultMap);
    
    private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, List<Class<?>> constructorArgTypes, List<Object> constructorArgs, String columnPrefix)
      throws SQLException {
    final Class<?> resultType = resultMap.getType();
    final MetaClass metaType = MetaClass.forClass(resultType, reflectorFactory);
    final List<ResultMapping> constructorMappings = resultMap.getConstructorResultMappings();
    if (typeHandlerRegistry.hasTypeHandler(resultType)) {
      return createPrimitiveResultObject(rsw, resultMap, columnPrefix);
    } else if (!constructorMappings.isEmpty()) {
      return createParameterizedResultObject(rsw, resultType, constructorMappings, constructorArgTypes, constructorArgs, columnPrefix);
    } else if (resultType.isInterface() || metaType.hasDefaultConstructor()) {
    //这里可以看出我们的objectFactory的使用方式,底层用来创建一个查询结果类型的实例对象;
      return objectFactory.create(resultType);
    } else if (shouldApplyAutomaticMappings(resultMap, false)) {
      return createByConstructorSignature(rsw, resultType, constructorArgTypes, constructorArgs, columnPrefix);
    }
    throw new ExecutorException("Do not know how to create an instance of " + resultType);
    }
    
    /*
    使用DefaultResultSetHandler往上面创建的对象属性中设值
    <!--private void setBeanProperty(PropertyTokenizer prop, Object object, Object value) {
    try {
      Invoker method = metaClass.getSetInvoker(prop.getName());
      Object[] params = {value};
      try {
        method.invoke(object, params);-->
    
    */   
    private boolean applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {
    final List<String> unmappedColumnNames = rsw.getUnmappedColumnNames(resultMap, columnPrefix);
    boolean foundValues = false;
    
    for (String columnName : unmappedColumnNames) {
      String propertyName = columnName;
      if (columnPrefix != null && !columnPrefix.isEmpty()) {
        // When columnPrefix is specified,
        // ignore columns without the prefix.
        if (columnName.toUpperCase(Locale.ENGLISH).startsWith(columnPrefix)) {
          propertyName = columnName.substring(columnPrefix.length());
        } else {
          continue;
        }
      }
      final String property = metaObject.findProperty(propertyName, configuration.isMapUnderscoreToCamelCase());//查找对应的属性
      if (property != null && metaObject.hasSetter(property)) {
        final Class<?> propertyType = metaObject.getSetterType(property);//获取属性的类型
        if (typeHandlerRegistry.hasTypeHandler(propertyType)) {
          final TypeHandler<?> typeHandler = rsw.getTypeHandler(propertyType, columnName);
          final Object value = typeHandler.getResult(rsw.getResultSet(), columnName);//得到对应属性,从库中查询出来的值
          // issue #377, call setter on nulls
          if (value != null || configuration.isCallSettersOnNulls()) {
            if (value != null || !propertyType.isPrimitive()) {
              metaObject.setValue(property, value);//设值到对应属性
            }
            foundValues = true;
          }
        }
      }
    }
    return foundValues;
    }
    

未经允许不得转载:SEARU.ORG » MyBatis 一句sql的执行流程

赞 (0)
分享到:更多 ()

评论 0