写在前面
TransactionStatus表示一个具体的事务状态(这里应用到了Java的一个多继承,接口允许多继承)
TransactionStatus它继承了SavepointManager接口,SavepointManager是对事务中上述保存点功能的封装(Spring利用保存点功能实现了事务的嵌套功能。后面会详细说明)
public interface SavepointManager { Object createSavepoint() throws TransactionException; void rollbackToSavepoint(Object savepoint) throws TransactionException; void releaseSavepoint(Object savepoint) throws TransactionException;}
public interface TransactionStatus extends SavepointManager, Flushable { //是否是一个新的事物 boolean isNewTransaction(); //是否有保存点 boolean hasSavepoint(); void setRollbackOnly(); //是否已被标记为回滚 boolean isRollbackOnly(); @Override void flush(); boolean isCompleted();}
DefaultTransactionStatus
常用的TransactionStatus接口实现为DefaultTransactionStatus:
public class DefaultTransactionStatus extends AbstractTransactionStatus { private final Object transaction; private final boolean newTransaction; private final boolean newSynchronization; private final boolean readOnly; private final boolean debug; private final Object suspendedResources;}
目前jdbc事务是通过Connection来实现事务的,Hibernate是通过它自己定义的Transaction来实现的,所以各家的事务都不同,所以Spring只能以Object transaction的形式来表示各家的事务,事务的回滚和提交等操作都会最终委托给上述Object transaction来完成。
Object transaction的职责就是提交回滚事务,这个transaction的选择可能如下:
-
- DataSourceTransactionObject
- HibernateTransactionObject
- JpaTransactionObject
详细信息分别如下:
- DataSourceTransactionObject:
我们使用了dataSource来获取连接,要想实现事务功能,必然需要使用Connection,所以它中肯定有一个Connection来执行事务的操作。DataSourceTransactionObject中有一个ConnectionHolder,它封装了一个Connection。
- HibernateTransactionObject:
我们使用了hibenrate,此时要想实现事务功能,必然需要通过hibernate自己定义的Transaction来实现。
HibernateTransactionObject中含有一个SessionHolder,和上面的ConnectionHolder一样,它封装了一个Session,有了Session,我们就可以通过Session来产生一个Hibernate的Transaction,从而实现事务操作。
DefaultTransactionStatus的获取
DefaultTransactionStatus的获取是事务管理器的方法,这里的实现是AbstractPlatformTransactionManager提供的模板方法
在获取Object transaction之后,先进行判断,是否是已存在的事务。因为这个Object transaction的获取过程就是直接从线程绑定的获取的,可能当前线程已经存在事务
@Override public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException { //获取相应的Object transaction Object transaction = doGetTransaction(); //就是依据和当前线程绑定的ConnectionHolder中是否已存在事务(也是依据和当前线程绑定的SessionHolder是否已存在事务) if (isExistingTransaction(transaction)) { //如果是已存在事务:则需要对事务的传播属性进行处理,如下即上述截图中的的handleExistingTransaction方法: return handleExistingTransaction(definition, transaction, debugEnabled); } ...}
如果是已存在事务:则需要对事务的传播属性进行处理,如下即上述截图中的的handleExistingTransaction方法
private TransactionStatus handleExistingTransaction( TransactionDefinition definition, Object transaction, boolean debugEnabled) throws TransactionException { // PROPAGATION_NEVER:不允许存在事务,如果存在抛出异常 if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) { throw new IllegalTransactionStateException( "Existing transaction found for transaction marked with propagation 'never'"); } // PROPAGATION_NOT_SUPPORTED:不支持事务,如果存在事务,则需将事务挂起,保存起来,当执行完成之后,需要将挂起的事务继续恢复 if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) { if (debugEnabled) { logger.debug("Suspending current transaction"); } Object suspendedResources = suspend(transaction); boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS); return prepareTransactionStatus( definition, null, false, newSynchronization, debugEnabled, suspendedResources); } //PROPAGATION_REQUIRES_NEW:开启一个新的事务,如果当前存在事务则把当前事务挂起来 if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) { if (debugEnabled) { logger.debug("Suspending current transaction, creating new transaction with name [" + definition.getName() + "]"); } SuspendedResourcesHolder suspendedResources = suspend(transaction); try { boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); DefaultTransactionStatus status = newTransactionStatus( definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); //可以看到,创建新的事务,就会调用doBegin(transaction, definition);方法,将事务开启。 doBegin(transaction, definition); prepareSynchronization(status, definition); return status; } catch (RuntimeException beginEx) { resumeAfterBeginException(transaction, suspendedResources, beginEx); throw beginEx; } catch (Error beginErr) { resumeAfterBeginException(transaction, suspendedResources, beginErr); throw beginErr; } } if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { if (!isNestedTransactionAllowed()) { throw new NestedTransactionNotSupportedException( "Transaction manager does not allow nested transactions by default - " + "specify 'nestedTransactionAllowed' property with value 'true'"); } if (debugEnabled) { logger.debug("Creating nested transaction with name [" + definition.getName() + "]"); } if (useSavepointForNestedTransaction()) { // Create savepoint within existing Spring-managed transaction, // through the SavepointManager API implemented by TransactionStatus. // Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization. DefaultTransactionStatus status = prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null); status.createAndHoldSavepoint(); return status; } else { // Nested transaction through nested begin and commit/rollback calls. // Usually only for JTA: Spring synchronization might get activated here // in case of a pre-existing JTA transaction. boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); DefaultTransactionStatus status = newTransactionStatus( definition, transaction, true, newSynchronization, debugEnabled, null); doBegin(transaction, definition); prepareSynchronization(status, definition); return status; } } // Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED. //PROPAGATION_SUPPORTS 和 PROPAGATION_REQUIRED 如果当前存在事务,则仍旧使用该事物 if (debugEnabled) { logger.debug("Participating in existing transaction"); } if (isValidateExistingTransaction()) { if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) { Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel(); if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) { Constants isoConstants = DefaultTransactionDefinition.constants; throw new IllegalTransactionStateException("Participating transaction with definition [" + definition + "] specifies isolation level which is incompatible with existing transaction: " + (currentIsolationLevel != null ? isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) : "(unknown)")); } } if (!definition.isReadOnly()) { if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) { throw new IllegalTransactionStateException("Participating transaction with definition [" + definition + "] is not marked as read-only but existing transaction is"); } } } boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null); }
事务的挂起
对于DataSourceTransactionManager来说,事务的挂起,就是把当前线程关联的ConnectionHolder解除绑定、同理事务的恢复就是把上述ConnectionHolder再重新绑定到当前线程,继续执行该事务
@Override protected Object doSuspend(Object transaction) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction; txObject.setConnectionHolder(null); //解除绑定dataSource, conHolder 至 TransactionSynchronizationManager ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.unbindResource(this.dataSource); return conHolder; } @Override protected void doResume(Object transaction, Object suspendedResources) { ConnectionHolder conHolder = (ConnectionHolder) suspendedResources; //重新绑定dataSource, conHolder 至 TransactionSynchronizationManager TransactionSynchronizationManager.bindResource(this.dataSource, conHolder); }