mybatis 3.4.2 DefaultSqlSessionFactory的優化版SqlSessionManager
d前面介紹 DefaultSqlSessionFactory 可以獲取操作SQL的 session例項。
從下面的程式碼可以看出,每次呼叫openSession 的時候,都會建立一個新的DefaultSession的例項。
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);
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();
}
}
SqlSessionManager是對 DefaultSqlSessionFactory的一個封裝。
public static SqlSessionManager newInstance(SqlSessionFactory sqlSessionFactory) {
return new SqlSessionManager(sqlSessionFactory);
}
寫錯了吧?怎麼是 SqlSessionManager 封裝 SqlSessionFactory, SqlSessionManager是管理session的吧!
沒錯!
來看個圖:
SqlSessionFactoryBuilder 負責接收mybatis-config.xml的輸入流,建立 DefaultSqlSessionFactory 例項。
DefaultSqlSessionFactory實現了 SqlSessionFactory 介面。
SqlSessionManager實現了SqlSessionFactory介面,又封裝了 DefaultSqlSessionFactory。
Java的代理模式,或者裝飾者模式!
與DefaultSqlSessionFactory不同的是,SqlSessionManager提供了一個本地執行緒變數,每當通過startManagedSession()獲得session例項的時候,會在本地執行緒儲存session例項。這是其一不同。
public void startManagedSession() {
this.localSqlSession.set(openSession());
}
其二,SqlSessionManager 實現了Session介面。意味著,SqlSessionManager集成了 sqlSessionFactory和session 的功能。通過SqlSessionManager,開發者可以不在理會SqlSessionFacotry的存在,直接面向Session程式設計。
SqlSessionManager 內部提供了一個sqlSessionProxy,這個sqlSessionProxy提供了所有Session介面的實現,而實現中正是使用了上面提到的本地執行緒儲存的session例項。
這樣,在同一個執行緒實現不同的sql操作,可以複用本地執行緒session,避免了DefaultSqlSessionFactory實現的每一個sql操作都要建立新的session例項。