mybatis

mybatis源码分析-selectOne-02

2019-10-07  本文已影响0人  愤怒的奶牛

上篇说到 DefaultSqlSession 中的 selectList() 方法,知道 执行具体的查询是 交给了 executor 接口。接下来我们接着看

  @Override
  public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
    try {
      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();
    }
  }
executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
1.1 Executor 接口
/**
 * @author Clinton Begin
 */
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;

  <E> Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) 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);

}

到这里我们又要看具体的实现类,先看一下类图:


Executor.png

接下来我们需要知道 executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER); 这句代码走的是哪一个实现类,我们可以debug 一下,然后我们再从源码里面找具体的代码。debug 得出的 是 CachingExecutor ,我们接下来分析为什么是 这个实现类,当前executor.query() 是在DefaultsSqlSession 接口中,所以我们现需要从 DefaultsSqlSession 中找到答案。为了方便阅读我们贴一下 DefaultSqlSessionFactory 中的源码:工厂模式体现

public class DefaultSqlSessionFactory implements SqlSessionFactory {

  private final Configuration configuration;

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

  @Override
  public SqlSession openSession() {
    return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
  }

  @Override
  public SqlSession openSession(boolean autoCommit) {
    return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, autoCommit);
  }

  @Override
  public SqlSession openSession(ExecutorType execType) {
    return openSessionFromDataSource(execType, null, false);
  }

  @Override
  public SqlSession openSession(TransactionIsolationLevel level) {
    return openSessionFromDataSource(configuration.getDefaultExecutorType(), level, false);
  }

  @Override
  public SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level) {
    return openSessionFromDataSource(execType, level, false);
  }

  @Override
  public SqlSession openSession(ExecutorType execType, boolean autoCommit) {
    return openSessionFromDataSource(execType, null, autoCommit);
  }

  @Override
  public SqlSession openSession(Connection connection) {
    return openSessionFromConnection(configuration.getDefaultExecutorType(), connection);
  }

  @Override
  public SqlSession openSession(ExecutorType execType, Connection connection) {
    return openSessionFromConnection(execType, connection);
  }

  @Override
  public Configuration getConfiguration() {
    return configuration;
  }
// 上面的方法都会复用这里的方法。至于为什么是 DefaultSqlSession 接口 可以参考上一篇文章 selectOne-01
  private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
    try {
      final Environment environment = configuration.getEnvironment();
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
//初始化了 Executor  对象
      final Executor executor = configuration.newExecutor(tx, execType);
// 创建 DefaultSqlSession 对象,并传入 Executor   对象,所以答案就在这里,这里就说明了 DefaultSqlSession 中使用的 Executor   对象。
      return new DefaultSqlSession(configuration, executor, 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();
    }
  }
... 部分方法省略
1.2 final Executor executor =configuration.newExecutor(tx, execType);
  final Executor executor = configuration.newExecutor(tx, execType); //创建了 Executor  对象,接下来我们就来分析 这个对象具体的 实现是哪个
public class Configuration {

  protected Environment environment;

  .... 省略部分
  protected boolean cacheEnabled = true;
 .... 省略部分
 // SqlSession sqlSession = sqlSessionFactory.openSession();
  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 { // executorType 默认值  ExecutorType.SIMPLE,所以会执行 下面这句话
      executor = new SimpleExecutor(this, transaction);
    }
    if (cacheEnabled) {// true
      executor = new CachingExecutor(executor); // 委派模式
    }
    executor = (Executor) interceptorChain.pluginAll(executor);
    return executor;
  }
  if (cacheEnabled) {// true
      executor = new CachingExecutor(executor); // 静态代理
    }

这里补贴一下 openSession() 方法的逻辑,这里有一点 跳跃 ,但是这里的 源码中的逻辑 比较简单 ,容易看懂,我们可以进源码仔细
跟一下我们 能够容易的得出 onfiguration.getDefaultExecutorType() => ExecutorType defaultExecutorType = ExecutorType.SIMPLE;

DefaultSqlSessionFactory 中
 @Override
  public SqlSession openSession() {
// configuration.getDefaultExecutorType() => ExecutorType defaultExecutorType = ExecutorType.SIMPLE;
    return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
  }

上面这就告诉我们,我们拿到的对象是 CachingExecutor 对象。该对象 通过静态代理的方式,目标对象是 SimpleExecutor 接口。
从上面的源码分析中,我们就能回答前面的问题了 ,
Executor 接口 的实现类就 是 CachingExecutor 。更具体一点,CachingExecutor 接口采用委派模式 ,委派模式中的特点之一就是 ,自己一定不会干活,干活的都是下面的,所以 我们可以说 Executor 接口 中执行 具体查询 任务的是 SimpleExecutor 接口。至于为什么要有 CachingExecutor 接口,我们到后面再来分析,为了不 淹没我们的主线任务,暂时不分析 具体原因,但有一点能肯定:就是优化查询。后面我们会 分析 CachingExecutor 接口 ,以及 SimpleExecutor 接口,涉及到的理论就是 静态代理。敬请关注 mybatis源码分析-selectOne-03

上一篇 下一篇

猜你喜欢

热点阅读