1. 从selectList看Mybatis中一个sql 是如何

2020-01-15  本文已影响0人  元隐
  1. 首页https://www.jianshu.com/p/39106eac8081
  2. Configuration https://www.jianshu.com/p/97522192011b
  3. DynamicSqlSource https://www.jianshu.com/p/2938876957ab
  4. PreparedStatement https://www.jianshu.com/p/5979f2514af3
  5. Parameter https://www.jianshu.com/p/8b93b0b1b7cf
  6. InterceptorChainhttps://www.jianshu.com/p/2d28f7c1a780
  7. StatementHandler https://www.jianshu.com/p/e82e846ac680
  8. ResultSetHandler https://www.jianshu.com/p/63d61dda0f25

致敬作者[克林顿·贝京]

Clinton Begin is a Senior Developer and Agile Mentor for ThoughtWorks Canada. He has been building enterprise applications for nine years based on platforms such as Java and .NET. Clinton has extensive experience with agile methodologies, persistence frameworks, and relational databases. He is the original creator of the iBATIS persistence framework, which he designed in response to the challenges faced by object oriented developers dealing with enterprise relational databases

这是一张ibatis的结构图, 略做参考

image
@see https://www.ibm.com/developerworks/cn/java/j-lo-ibatis-principle/index.html

一个SQL的执行过程

由configuration解析,获取MappedStatement, variables
由SqlSession的executor 最终执行

sql参数

sql

一个典型的SQL, 由statement,parameter,RowBounds(分页参数)组成
如下:

public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) 

一个典型的statement

<select id="queryById" resultType= ..>

statement由注解或xml生成, 由configuration管理

configuration.getMappedStatement(statement)
MappedStatement getMappedStatement(String id)

configuration详见configuration章节
MappedStatement由XML/... StatementBuilder 产生

paramter

查询参数 详见paramter章节

BoundSql

可以看到BoundSql由sqlSource获取到. sqlSource有若干实现类, 包含我们常见的xml SqlSource, 还有annotation SqlSource
DynamicSqlSource 详见DynamicSqlSource 章节

public BoundSql getBoundSql(Object parameterObject) {
    BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
    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();
        }
      }
    }

    return boundSql;
  }

rowbounds

分页参数,见 rowbounds章节

sql执行

Mybatis Sql执行由Executor负责
org.apache.ibatis.executor.Executor

每个SqlSession需要注入executor

public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
    this.configuration = configuration;
    this.executor = executor;
    this.dirty = false;
    this.autoCommit = autoCommit;
  }

Configuration如无特殊指定,采用的是SimpleExecutor
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);
    }
    executor = (Executor) interceptorChain.pluginAll(executor);
    return executor;
  }

四个executor网上对比很多, SimpleExecutor每次都会采用新用statement, 性能稍差, 但ReuseExecutor由于是session级别的, 性能提升有限. 

doQuery sql执行

interceptorChain 参见interceptorChain

 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();
      StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
      stmt = prepareStatement(handler, ms.getStatementLog());
      return handler.query(stmt, resultHandler);
    } 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;
  }
上一篇下一篇

猜你喜欢

热点阅读