MyBatis執行原理(二)SqlSession物件建立過程分析
阿新 • • 發佈:2019-02-08
在上一篇博文中分析了SqlSessionFactory
物件建立的過程,有了SqlSessionFactory
物件工廠就可以建立SqlSession
了,下面就來具體分析一下SqlSession
物件建立的過程。
一、SqlSession
物件建立過程分析
入口程式:
private SqlSessionFactory getSqlSessionFactory() throws IOException {
String resource = "mybatis-config.xml";
InputStream is = Resources.getResourceAsStream(resource);
return new SqlSessionFactoryBuilder().build(is);
}
@Test
public void testMyBatis3Simple() throws IOException {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
// 將斷點打在下面程式碼的前面
SqlSession sqlSession = sqlSessionFactory.openSession();
}
1.首先會跳到DefaultSqlSessionFactory
類中的openSession()
方法中。
// ====== DefaultSqlSessionFactory 類中的方法 ======
@Override
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
在上面這個方法中呼叫了另一個方法:
openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit)
// ====== 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);
/**
* ExecutorType 是一個列舉型別,預設是SIMPLE
* 根據ExecutorType 建立一個Executor 物件
* 因為Executor 物件比較重要,下面來分析一下Executor 物件建立的過程
*/
final Executor executor = configuration.newExecutor(tx, execType);
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();
}
}
2.configuration.newExecutor(tx, execType)
建立過程如下:
// ====== Configuration 類中的方法 ======
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
executorType = executorType == null ? defaultExecutorType : executorType;
executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
Executor executor;
/**
* 根據executorType 型別建立對應的Executor
* BatchExecutor:批量執行器
* ReuseExecutor:會執行預處理的執行器
* SimpleExecutor:簡單的執行器
*/
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);
}
/**
* 如果開啟了二級快取,則使用CachingExecutor 來包裝executor,
* 在查詢之前都會先查詢快取中是否有對應的資料
* 包裝的過程使用了裝飾者模式,裝飾者模式可參考博文:
* http://blog.csdn.net/codejas/article/details/79112824
*/
if (cacheEnabled) {
executor = new CachingExecutor(executor);
// 最後使用每個攔截器重新包裝executor 並返回
executor = (Executor) interceptorChain.pluginAll(executor);
// executor 物件建立完成並返回
return executor;
}
3.Executor
物件建立完成後,會接著執行
openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit)
方法。
// ====== 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);
/**
* configuration 物件在建立SqlSessionFactory 物件的時候就已經建立了
* Executor 物件建立完成後,使用executor與configuration 物件來建立DefaultSqlSession
* 返回DefaultSqlSession 物件
*/
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();
}
}
到這裡會接著向上一步返回,SqlSession
物件建立的過程也就結束了。
呼叫過程時序圖:
二、總結
這篇博文對sqlSessionFactory
建立SqlSession
物件的過程進行了原始碼分析,最後返回的SqlSession
中包含有兩個重要的物件,分別是configuration
與executor
。configuration
物件在建立SqlSessionFactory
的時候就已經被創建出來了,用來儲存全域性配置檔案與SQL 對映檔案中的資訊,executor
是一個執行器物件。如果你想了解更多的細節,可以自己檢視原始碼,希望這篇博文能夠為你提供幫助。