關於mybatis裏面的Executor

使用mybatis查尋數據,跟蹤其執行流程

最開始執行的語句

this.getSqlSession().selectList("QUERY-QUESTION", data, rowBounds);

這裏需要找到sqlsession是從哪裏來的

getSqlSession是SqlSessionDaoSupport類裏面的方法,該類通過spring的自動注入可以把sqlSessionTemplate注入進來,當然這裏的sqlSessionTemplate是需要spring配置的

  @Autowired(required = false)
  public final void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
    this.sqlSession = sqlSessionTemplate;
    this.externalSqlSession = true;
  }

<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
		<constructor-arg index="0" ref="sqlSessionFactory"/>
		<constructor-arg index="1" value="BATCH"/>
	</bean>

@Autowired(required = false)是通過類型匹配來注入的,如果沒有找到相應對,就不用注入

所以selectList方法爲SqlSessionTemlate裏面的,再看SqlSessionTemplage,裏面的都是通過sqlSessionProxy來執行selectList方法的,也就是通過代理方式來的

  public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType,
      PersistenceExceptionTranslator exceptionTranslator) {

    notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required");
    notNull(executorType, "Property 'executorType' is required");

    this.sqlSessionFactory = sqlSessionFactory;
    this.executorType = executorType;
    this.exceptionTranslator = exceptionTranslator;
    this.sqlSessionProxy = (SqlSession) newProxyInstance(
        SqlSessionFactory.class.getClassLoader(),
        new Class[] { SqlSession.class },
        new SqlSessionInterceptor());
  }

這裏用到了java的動態代理,詳細可以見java api,有詳細的說明

SqlSessionInterceptor實現了InvocationHandler,在invoke方法裏面的開始有這樣代碼,那裏是真正的sqlsession

 final SqlSession sqlSession = getSqlSession(
          SqlSessionTemplate.this.sqlSessionFactory,
          SqlSessionTemplate.this.executorType,
          SqlSessionTemplate.this.exceptionTranslator);

跟蹤geteSqlSession可以找到他的創建來源,見

SqlSession session = sessionFactory.openSession(executorType);

繼續跟蹤可以找到DefaultSqlSessionFactory裏面的該方法

  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);
      final Executor executor = configuration.newExecutor(tx, execType, autoCommit);
      return new DefaultSqlSession(configuration, executor);
    } 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();
    }
  }

通過
 final Executor executor = configuration.newExecutor(tx, execType, autoCommit);

你就知道executor是怎麼回來的了

mybatis默認使用了cache,在創建exector時,外面就包了一層CacheExecutor,詳細見

  public Executor newExecutor(Transaction transaction, ExecutorType executorType, boolean autoCommit) {
    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, autoCommit);
    }
    executor = (Executor) interceptorChain.pluginAll(executor);
    return executor;
  }

CachingExecutor可以使mybatis先從緩存中提取數據,數據緩存中沒有數據時才從數據庫裏面提取數據
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章