mybatis與hibernate常用的持久化類,及sqlsession和sqlsessionTemplate區別


首先, 通過翻閱源碼,我們來整理一下mybatis進行 持久化操作時重要的幾個類:
SqlSessionFactoryBuilder:build方法創建SqlSessionFactory實例。
SqlSessionFactory:創建SqlSession實例的工廠。

SqlSession:用於執行 持久化操作的對象,類似於jdbc中的Connection。
SqlSessionTemplate:MyBatis提供的持久層訪問模板化的工具, 線程安全,可通過構造參數或 依賴注入SqlSessionFactory實例。

Hibernate是與MyBatis類似的 orm框架,這里與Hibernate進行一下對比,Hibernate中對於connection的管理,是通過以下幾個重要的類:
SessionFactory:創建Session實例的工廠,類似於MyBatis中的SqlSessionFactory。
Session:用來執行 持久化操作的對象,類似於jdbc中的Connection。

HibernateTemplate:Hibernate提供的持久層訪問模板化的工具, 線程安全,可通過構造參數或 依賴注入SessionFactory實例。

在日常的開發中,我們經常需要這樣對MyBatis和Spring進行集成,把sqlSessionFactory交給Spring管理,通常情況下,我們這樣配置:
?

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
</bean>

通過上面的配置,Spring將自動創建一個SqlSessionFactory對象,其中使用到了org.mybatis.spring.SqlSessionFactoryBean,其 是MyBatis為Spring
提供的用於創建SqlSessionFactory的類,將在Spring應用程序的上下文建議一下可共享的 MyBatis SqlSessionFactory實例,我們可以通過 依賴注入
SqlSessionFactory傳遞給MyBatis的一些接口。

如果通過Spring進行事務的管理,我們需要增加Spring注解的 事務管理機制,如下配置:
?

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>

<tx:annotation-driven/>

這樣,我們就可以使用Spring @Transactional注解,進行事務的控制,表明所注釋的方法應該在一個事務中運行。 Spring將在事務成功完成后提交事務,
在事務發生錯誤時進行異常回滾,而且,Spring會將產生的MyBatis異常轉換成適當的 DataAccessExceptions,從而提供具體的異常信息。

下面,我們通過分析SqlSessionUtils中getSession的源碼,來詳細的了解一下sqlSession的產生過程,源碼如下:
public static SqlSession getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType,
PersistenceExceptionTranslator exceptionTranslator) {

notNull(sessionFactory, "No SqlSessionFactory specified");
notNull(executorType, "No ExecutorType specified");

SqlSessionHolder holder = (SqlSessionHolder) getResource(sessionFactory);

if (holder != null && holder.isSynchronizedWithTransaction()) {
if (holder.getExecutorType() != executorType) {
throw new TransientDataAccessResourceException("Cannot change the ExecutorType when there is an existing transaction");
}

holder.requested();

if (logger.isDebugEnabled()) {
logger.debug("Fetched SqlSession [" + holder.getSqlSession() + "] from current transaction");
}

return holder.getSqlSession();
}

if (logger.isDebugEnabled()) {
logger.debug("Creating a new SqlSession");
}

SqlSession session = sessionFactory.openSession(executorType);

// Register session holder if synchronization is active (i.e. a Spring TX is active)
//
// Note: The DataSource used by the Environment should be synchronized with the
// transaction either through DataSourceTxMgr or another tx synchronization.
// Further assume that if an exception is thrown, whatever started the transaction will
// handle closing / rolling back the Connection associated with the SqlSession.
if (isSynchronizationActive()) {
Environment environment = sessionFactory.getConfiguration().getEnvironment();

if (environment.getTransactionFactory() instanceof SpringManagedTransactionFactory) {
if (logger.isDebugEnabled()) {
logger.debug("Registering transaction synchronization for SqlSession [" + session + "]");
}

holder = new SqlSessionHolder(session, executorType, exceptionTranslator);
bindResource(sessionFactory, holder);
registerSynchronization(new SqlSessionSynchronization(holder, sessionFactory));
holder.setSynchronizedWithTransaction(true);
holder.requested();
} else {
if (getResource(environment.getDataSource()) == null) {
if (logger.isDebugEnabled()) {
logger.debug("SqlSession [" + session + "] was not registered for synchronization because DataSource is not transactional");
}
} else {
throw new TransientDataAccessResourceException(
"SqlSessionFactory must be using a SpringManagedTransactionFactory in order to use Spring transaction synchronization");
}
}
} else {
if (logger.isDebugEnabled()) {
logger.debug("SqlSession [" + session + "] was not registered for synchronization because synchronization is not active");
}
}

return session;
}

上面的getSession方法,會從Spring的 事務管理器中獲取一個SqlSession或創建一個新的SqlSession,將試圖從當前事務中得到一個SqlSession,然后,如果配置
事務管理器的工廠並且Spring 的事務管理器是活躍的,它將會鎖定當前事務的SqlSession,保證同步。主要是通過以下幾個步驟進行SqlSession的創建:
它會首先獲取SqlSessionHolder,SqlSessionHolder用於在TransactionSynchronizationManager中保持當前的SqlSession。
如果holder不為空,並且holder被事務鎖定,則可以通過holder.getSqlSession()方法,從當前事務中獲取sqlSession,即 Fetched SqlSession from current transaction。

如果不存在holder或沒有被事務鎖定,則會創建新的sqlSession,即 Creating a new SqlSession,通過sessionFactory.openSession()方法。

如果當前線程的事務是活躍的,將會為SqlSession注冊事務同步,即 Registering transaction synchronization for SqlSession。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM