spring---transaction(3)---源代码分析(事务的管理器PlatformTransactionManager)
写在前面
由于实现事务功能的方式各不相同,Spring进行了统一的抽象,形成了PlatformTransactionManager事务管理器顶级接口(平台事务管理器),事务的提交、回滚等操作全部交给它来实现
先来看下三大接口
-
-
PlatformTransactionManager : 事务管理器
-
TransactionDefinition : 事务的一些基础信息,如超时时间、隔离级别、传播属性等
-
TransactionStatus : 事务的一些状态信息,如是否是一个新的事务、是否已被标记为回滚
-
一般我们给事务管理器的默认实现为DataSourceTransactionManager
<!-- 事务管理器配置 --> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean>
DataSourceTransactionManager(事务管理器接口定义PlatformTransactionManager)
PlatformTransactionManager
- AbstractPlatformTransactionManager
- DataSourceTransactionManager(重点)
- HibernateTransactionManager
- JpaTransactionManager
public interface PlatformTransactionManager { //获取一个具体的事务状态信息 TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException; //提交一个事务状态信息 void commit(TransactionStatus status) throws TransactionException; //回滚一个事务状态信息 void rollback(TransactionStatus status) throws TransactionException; }
获取Object transaction:
大体内容就是先获取上述说明(TransactionStatus)的Object transaction,判断当前事务是否已存在,如果存在则进行事务的传播属性处理,后面详细说明,如果不存在new DefaultTransactionStatus,新创建一个事务,同时使用Object transaction开启事务。 分成了几个过程:
- 获取Object transaction:不同的事务管理器获取不同的Object transaction
DataSourceTransactionManager就是获取上述的DataSourceTransactionObject
从当前线程中获取绑定的ConnectionHolder,可能为null,如果为null,则会在下一个开启事务的过程中,从dataSource中获取一个Connection,封装成ConnectionHolder,然后再绑定到当前线程
然后我们new 一个DataSourceTransactionObject了,具体过程如下:
@Override protected Object doGetTransaction() { DataSourceTransactionObject txObject = new DataSourceTransactionObject(); txObject.setSavepointAllowed(isNestedTransactionAllowed()); ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource); txObject.setConnectionHolder(conHolder, false); return txObject; }
HibernateTransactionManager获取HibernateTransactionObject
从当前线程中获取绑定的SessionHolder,可能为null,如果为null,则会在下一个开启事务的过程中从sessionFactory中获取一个session,然后封装成SessionHolder,然后再绑定到当前线程
然后我们就可以new 一个HibernateTransactionObject了,具体过程如下:
@Override protected Object doGetTransaction() { HibernateTransactionObject txObject = new HibernateTransactionObject(); txObject.setSavepointAllowed(isNestedTransactionAllowed()); SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory()); if (sessionHolder != null) { if (logger.isDebugEnabled()) { logger.debug("Found thread-bound Session [" + sessionHolder.getSession() + "] for Hibernate transaction"); } txObject.setSessionHolder(sessionHolder); } else if (this.hibernateManagedSession) { try { Session session = this.sessionFactory.getCurrentSession(); if (logger.isDebugEnabled()) { logger.debug("Found Hibernate-managed Session [" + session + "] for Spring-managed transaction"); } txObject.setExistingSession(session); } catch (HibernateException ex) { throw new DataAccessResourceFailureException( "Could not obtain Hibernate-managed Session for Spring-managed transaction", ex); } } if (getDataSource() != null) { ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(getDataSource()); txObject.setConnectionHolder(conHolder); } return txObject; }
2. 构建DefaultTransactionStatus,使用Object transaction开启事务
DataSourceTransactionManager的DataSourceTransactionObject开启过程如下:
首先判断之前的获取当前线程绑定的ConnectionHolder是否为null,如果为null,从dataSource中获取一个Connection,封装成ConnectionHolder,然后再绑定到当前线程因为开启了一个事务,则必须要关闭DataSourceTransactionObject中Connection的自动提交
@Override protected void doBegin(Object transaction, TransactionDefinition definition) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction; Connection con = null; try { if (txObject.getConnectionHolder() == null || txObject.getConnectionHolder().isSynchronizedWithTransaction()) { Connection newCon = this.dataSource.getConnection(); if (logger.isDebugEnabled()) { logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction"); } txObject.setConnectionHolder(new ConnectionHolder(newCon), true); } txObject.getConnectionHolder().setSynchronizedWithTransaction(true); con = txObject.getConnectionHolder().getConnection(); Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition); txObject.setPreviousIsolationLevel(previousIsolationLevel); // Switch to manual commit if necessary. This is very expensive in some JDBC drivers, // so we don't want to do it unnecessarily (for example if we've explicitly // configured the connection pool to set it already). if (con.getAutoCommit()) { txObject.setMustRestoreAutoCommit(true); if (logger.isDebugEnabled()) { logger.debug("Switching JDBC Connection [" + con + "] to manual commit"); } con.setAutoCommit(false); } txObject.getConnectionHolder().setTransactionActive(true); int timeout = determineTimeout(definition); if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) { txObject.getConnectionHolder().setTimeoutInSeconds(timeout); } // Bind the session holder to the thread. if (txObject.isNewConnectionHolder()) { TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder()); } } catch (Throwable ex) { if (txObject.isNewConnectionHolder()) { DataSourceUtils.releaseConnection(con, this.dataSource); txObject.setConnectionHolder(null, false); } throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex); } }
HibernateTransactionManager的HibernateTransactionObject开启过程如下:
也是同样的逻辑,如果SessionHolder为null,则从SessionFactory中获取一个Session,然后封装成SessionHolder,然后把这个SessionHolder绑定到当前线程
3. 第二个接口:void rollback(TransactionStatus status) 回滚事务
回滚,则还是利用DefaultTransactionStatus内部的Object transaction来执行回滚操作
DataSourceTransactionManager就是使用DataSourceTransactionObject中的Connection来进行回滚操作
@Override protected void doRollback(DefaultTransactionStatus status) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); Connection con = txObject.getConnectionHolder().getConnection(); if (status.isDebug()) { logger.debug("Rolling back JDBC transaction on Connection [" + con + "]"); } try { con.rollback(); } catch (SQLException ex) { throw new TransactionSystemException("Could not roll back JDBC transaction", ex); } }
HibernateTransactionManager就是使用HibernateTransactionObject中的SessionHolder中的Session创建的事务Transaction来进行回滚操作
@Override protected void doRollback(DefaultTransactionStatus status) { HibernateTransactionObject txObject = (HibernateTransactionObject) status.getTransaction(); if (status.isDebug()) { logger.debug("Rolling back Hibernate transaction on Session [" + txObject.getSessionHolder().getSession() + "]"); } try { txObject.getSessionHolder().getTransaction().rollback(); } catch (org.hibernate.TransactionException ex) { throw new TransactionSystemException("Could not roll back Hibernate transaction", ex); } catch (HibernateException ex) { // Shouldn't really happen, as a rollback doesn't cause a flush. throw convertHibernateAccessException(ex); } finally { if (!txObject.isNewSession() && !this.hibernateManagedSession) { // Clear all pending inserts/updates/deletes in the Session. // Necessary for pre-bound Sessions, to avoid inconsistent state. txObject.getSessionHolder().getSession().clear(); } } }
4.第三个接口: void commit(TransactionStatus status) 提交事务
同理,DataSourceTransactionManager依托内部的Connection来完成提交操作
HibernateTransactionManager依托内部的Transaction来完成提交操作