最開始執行的語句
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先從緩存中提取數據,數據緩存中沒有數據時才從數據庫裏面提取數據