Spring事务管理

什么是事务

数据库事务(Database Transaction)是指将一系列的数据库操作当作一个逻辑单元处理的操作,这个单元的所有数据库操作要么完全执行要么完全不执行。

事务的特性

一个逻辑单元要满足事务必须满足ACID(原子性、一致性、隔离性和持久性)属性。ACID的含义如下:

  • 原子性(Atomicity):一个事务内的操作要么全部执行成功,要么全部执行不成功;
  • 一致性(Consistency):事务执行后,数据库的状态和其他的业务规则保持一致。如转账业务,无论事务成功与否,转账的账号的余额总数应该保持不变;
  • 隔离性(Isolation):每个事务独立运行。并发环境下,事务是相互隔离的,互不影响;
  • 持久性(Durability):事务提交后,持久的保存再数据库中。

事务的隔离级别

READ_UNCOMMITTED

未提交读,即一个事务读取到了另一个事务未提交的数据。这种情况会造成“脏读”的现象。

时间轴事务A事务B
T1事务A开始---------
T2---------事务B开始
T3---------事务B查询余额为10元
T4---------事务B取出十元
T5事务A查出余额0元---------
T6事务A存入10元---------
T7事务提交更新余额为10元---------
T8---------事务B回滚事务

正常情况下,A B事务执行完,数据库余额应该是20元,由于T5时刻,A事务读取余额为0元,此时B事务尚未提交,造成了脏读,即读取到了脏数据。

READ_COMMITTED

在这个隔离级别下,可以有效的避免脏读的现象的发生,但是这个隔离级别却无法避免不可重复读的问题

时间轴事务A事务B
T1事务A开始---------
T2---------事务B开始
T3---------事务B查询余额为10元
T4事务A查询余额为10元---------
T5--------事务B取出10元
T6--------事务B提交
T7事务A查询余额为0元---------
T8事务A提交---------

在事务A中对余额进行了两次查询,但是两次结果却不一样,这就是不可重复读。

REPEATABLE_READ

可重复读级别保证了事务在多次读取同一个数据的时候,值始终是一致的。它的实现是在事务开启后,不允许其他的事务对这行记录进行修改。
这个隔离级别虽然避免了“脏读”和不可重复读的问题,但是还是可能会出现幻读的问题。

时间轴事务A事务B
T1事务A开始---------
T2---------事务B开始
T3查询交易记录---------
T4---------事务B取出10元
T5--------事务B提交

| T6| 查询交易记录 | ---------|
| T7| 事务A提交 | ---------|
事务A中,同一个事务获取交易的次数,发现第二次多了一笔交易数据,这就是幻读。

不可重复读是针对某一行数据的变化,重复读取数据不一致;幻读针对的是行数的变化

SERIALIZABLE

串行读取是最严格的事务隔离级别,它要求所有的事务都顺序执行,不能并发执行。

时间轴事务A事务B
T1事务A开始---------
T2事务A查询余额为10元---------
T3事务A存入10元---------
T4事务A提交---------
T5--------事务B开始
T6--------事务B查询余额为20元
T7--------事务B去除10元
T8--------事务B提交

Spring对事务的封装

Spring事务的隔离级别

事务的隔离级别脏读不可重复读幻读
ISOLATION_DEFAULT同数据库的默认隔离级别同数据库的默认隔离级别同数据库的默认隔离级别
ISOLATION_READ_UNCOMMITTED
ISOLATION_READ_COMMITED×
ISOLATION_REPEATABLE_READ××
ISOLATION_SERIALIZABLE×××

Spring的事务传播行为

事务传播行为是用来描述由某一个事务传播行为的方法被嵌套进另一个方法的时候,事务的表现出的行为。

事务传播行为类型说明
PROPAGATION_REQUIRED如果当前没有事务,则新建一个事务。如果存在一个事务则加入已存在的事务
PROPAGATION_SUPPORTS支持当前事务。SUPPORTS类型的事务传播机制,是否使用事务取决于调用方法是否有事务,如果有则直接用,如果没有则不使用事务
PROPAGATION_MANDATORYMANDATORY必须在已有事务下被调用,否则报错
PROPAGATION_REQUIRES_NEWS新建一个事务,如果当前存在事务则将当前事务挂起
PROPAGATION_NOT_SUPPORTEDNOT_SUPPORTED相当于没有Spring事务,每条执行语句单独执行,单独提交;如果当前存在事务,则将事务挂起
PROPAGATION_NEVERNEVER必须在没有事务的方法中执行,否则报错
PROPAGATION_NESTED如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与REQUIRED类似的操作;其与REQUIRES_NEWS的区别是,REQUIRES_NEWS会新建一个事务,与父事务相互独立,NESTED事务和父事务是相互依靠的,要等父事务一起提交

Spring事务的代码分析

Spring的事务是由Spring的AOP实现的,Spring的AOP在此不赘述,之后有机会开贴单独梳理。Spring的AOP中有个MethodInterceptor接口,源码如下:

public interface MethodInterceptor extends Interceptor {
	
	/**
	 * Implement this method to perform extra treatments before and
	 * after the invocation. Polite implementations would certainly
	 * like to invoke {@link Joinpoint#proceed()}.
	 */
	 //实现此方法的类可以在方法目标执行前后进行加强目标方法
	Object invoke(MethodInvocation invocation) throws Throwable;
}

Spring 的事务的核心类就是实现了此接口,并通过invoke方法,在目标方法执行前后加了事务处理逻辑。实现的类是TransactionInterceptor,源码如下:

public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {

	/**
	 * Create a new TransactionInterceptor.
	 * <p>Transaction manager and transaction attributes still need to be set.
	 * @see #setTransactionManager
	 * @see #setTransactionAttributes(java.util.Properties)
	 * @see #setTransactionAttributeSource(TransactionAttributeSource)
	 */
	public TransactionInterceptor() {
	}

	/**
	 * Create a new TransactionInterceptor.
	 * @param ptm the default transaction manager to perform the actual transaction management
	 * @param attributes the transaction attributes in properties format
	 * @see #setTransactionManager
	 * @see #setTransactionAttributes(java.util.Properties)
	 */
	public TransactionInterceptor(PlatformTransactionManager ptm, Properties attributes) {
		setTransactionManager(ptm);
		setTransactionAttributes(attributes);
	}

	/**
	 * Create a new TransactionInterceptor.
	 * @param ptm the default transaction manager to perform the actual transaction management
	 * @param tas the attribute source to be used to find transaction attributes
	 * @see #setTransactionManager
	 * @see #setTransactionAttributeSource(TransactionAttributeSource)
	 */
	public TransactionInterceptor(PlatformTransactionManager ptm, TransactionAttributeSource tas) {
		setTransactionManager(ptm);
		setTransactionAttributeSource(tas);
	}


	@Override
	@Nullable
	public Object invoke(final MethodInvocation invocation) throws Throwable {
		// Work out the target class: may be {@code null}.
		// The TransactionAttributeSource should be passed the target class
		// as well as the method, which may be from an interface.
		Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

		// Adapt to TransactionAspectSupport's invokeWithinTransaction...
		return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
	}


	//---------------------------------------------------------------------
	// Serialization support
	//---------------------------------------------------------------------

	private void writeObject(ObjectOutputStream oos) throws IOException {
		// Rely on default serialization, although this class itself doesn't carry state anyway...
		oos.defaultWriteObject();

		// Deserialize superclass fields.
		oos.writeObject(getTransactionManagerBeanName());
		oos.writeObject(getTransactionManager());
		oos.writeObject(getTransactionAttributeSource());
		oos.writeObject(getBeanFactory());
	}

	private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
		// Rely on default serialization, although this class itself doesn't carry state anyway...
		ois.defaultReadObject();

		// Serialize all relevant superclass fields.
		// Superclass can't implement Serializable because it also serves as base class
		// for AspectJ aspects (which are not allowed to implement Serializable)!
		setTransactionManagerBeanName((String) ois.readObject());
		setTransactionManager((PlatformTransactionManager) ois.readObject());
		setTransactionAttributeSource((TransactionAttributeSource) ois.readObject());
		setBeanFactory((BeanFactory) ois.readObject());
	}

}

这里我们重点关注invoke方法:

	public Object invoke(final MethodInvocation invocation) throws Throwable {
		// Work out the target class: may be {@code null}.
		// The TransactionAttributeSource should be passed the target class
		// as well as the method, which may be from an interface.
		Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

		// Adapt to TransactionAspectSupport's invokeWithinTransaction...
		return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
	}

此方法中调用了父类TransactionAspectSupport的invokeWithinTransaction方法:

	@Nullable
	protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
			final InvocationCallback invocation) throws Throwable {

		// If the transaction attribute is null, the method is non-transactional.
		TransactionAttributeSource tas = getTransactionAttributeSource();
		//获取事务的配置属性(就是@Transaction上面配置的那些值)
		final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
		//获取事务管理器
		final PlatformTransactionManager tm = determineTransactionManager(txAttr);
		final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

		if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
			// Standard transaction demarcation with getTransaction and commit/rollback calls.
			//关键----根据事务传播的属性做出不同的处理
			TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
			Object retVal = null;
			try {
				// This is an around advice: Invoke the next interceptor in the chain.
				// This will normally result in a target object being invoked.
				//正常执行目标方法
				retVal = invocation.proceedWithInvocation();
			}
			catch (Throwable ex) {
				// target invocation exception
				//处理异常回滚
				completeTransactionAfterThrowing(txInfo, ex);
				throw ex;
			}
			finally {
				cleanupTransactionInfo(txInfo);
			}
			//提交事务
			commitTransactionAfterReturning(txInfo);
			return retVal;
		}

		else {
			final ThrowableHolder throwableHolder = new ThrowableHolder();

			// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
			try {
				Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, status -> {
					TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
					try {
						return invocation.proceedWithInvocation();
					}
					catch (Throwable ex) {
						if (txAttr.rollbackOn(ex)) {
							// A RuntimeException: will lead to a rollback.
							if (ex instanceof RuntimeException) {
								throw (RuntimeException) ex;
							}
							else {
								throw new ThrowableHolderException(ex);
							}
						}
						else {
							// A normal return value: will lead to a commit.
							throwableHolder.throwable = ex;
							return null;
						}
					}
					finally {
						cleanupTransactionInfo(txInfo);
					}
				});

				// Check result state: It might indicate a Throwable to rethrow.
				if (throwableHolder.throwable != null) {
					throw throwableHolder.throwable;
				}
				return result;
			}
			catch (ThrowableHolderException ex) {
				throw ex.getCause();
			}
			catch (TransactionSystemException ex2) {
				if (throwableHolder.throwable != null) {
					logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
					ex2.initApplicationException(throwableHolder.throwable);
				}
				throw ex2;
			}
			catch (Throwable ex2) {
				if (throwableHolder.throwable != null) {
					logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
				}
				throw ex2;
			}
		}
	}

方法中的关键地方的注释已经给上,重点方法是createTransactionIfNecessary,根据不同的事务属性,进行不同的处理,源码如下:

	@SuppressWarnings("serial")
	protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
			@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {
		if (txAttr != null && txAttr.getName() == null) {
			txAttr = new DelegatingTransactionAttribute(txAttr) {
				@Override
				public String getName() {
					return joinpointIdentification;
				}
			};
		}

		TransactionStatus status = null;
		if (txAttr != null) {
			if (tm != null) {
				status = tm.getTransaction(txAttr);
			}
			else {
				if (logger.isDebugEnabled()) {
					logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
							"] because no transaction manager has been configured");
				}
			}
		}
		return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
	}

此方法中,关键是tm.getTransaction(txAttr),通过事务管理器调用其getTransaction方法,该方法的实现是在AbstractPlatformTransactionManager中,源码如下:

	public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
	    //获取事务对象
		Object transaction = doGetTransaction();

		// Cache debug flag to avoid repeated checks.
		boolean debugEnabled = logger.isDebugEnabled();

		if (definition == null) {
			// Use defaults if no transaction definition given.
			definition = new DefaultTransactionDefinition();
		}

		//判断当前是否存在事务
		if (isExistingTransaction(transaction)) {
			// 如果存在事务针对不同的事务行为进行针对处理
			return handleExistingTransaction(definition, transaction, debugEnabled);
		}

		if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
			throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
		}

		//如果不存在事务,且事务传播行为为PROPAGATION_MANDATORY,则抛出异常(呼应上文表格)
		if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
			throw new IllegalTransactionStateException(
					"No existing transaction found for transaction marked with propagation 'mandatory'");
		}
		//如果事务传播行为是PROPAGATION_REQUIRED  PROPAGATION_REQUIRES_NEW  PROPAGATION_NESTED
		else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
				definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
				definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
			SuspendedResourcesHolder suspendedResources = suspend(null);
			if (debugEnabled) {
				logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
			}
			try {
				boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
				DefaultTransactionStatus status = newTransactionStatus(
						definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
				doBegin(transaction, definition);
				prepareSynchronization(status, definition);
				return status;
			}
			catch (RuntimeException | Error ex) {
				resume(null, suspendedResources);
				throw ex;
			}
		}
		else {
			// Create "empty" transaction: no actual transaction, but potentially synchronization.
			if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
				logger.warn("Custom isolation level specified but no actual transaction initiated; " +
						"isolation level will effectively be ignored: " + definition);
			}
			boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
			return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
		}
	}

这段代码比较关键,根据注释我们一步步分析,第一步doGetTransaction(),老样子先进入源码看看干了啥:

    protected Object doGetTransaction() {
        DataSourceTransactionManager.DataSourceTransactionObject txObject = new DataSourceTransactionManager.DataSourceTransactionObject();
        txObject.setSavepointAllowed(this.isNestedTransactionAllowed());
        //从当前数据源中获取一个连接,包装成ConnectionHolder对象
        ConnectionHolder conHolder = (ConnectionHolder)TransactionSynchronizationManager.getResource(this.obtainDataSource());
        //将ConnectionHolder对象塞入前面new出来的txObject中,并返回
        txObject.setConnectionHolder(conHolder, false);
        return txObject;
    }

根据注释很明显,返回一个包装了数据源,数据库连接等等的事务对象txObject;接下来,我们判断当前是否存在事务了:

    protected boolean isExistingTransaction(Object transaction) {
        DataSourceTransactionManager.DataSourceTransactionObject txObject = (DataSourceTransactionManager.DataSourceTransactionObject)transaction;
        return txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive();
    }

txObject就是我们第一步包装的对象,根据这个对象是否有ConnectionHolder以及ConnectionHolder的的事务是否是否存活判断当前事务是否存在;
此时如果返回true,即事务存在,进入分支方法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);
				prepareSynchronization(status, definition);
				return status;
			}
			catch (RuntimeException | Error beginEx) {
				resumeAfterBeginException(transaction, suspendedResources, beginEx);
				throw beginEx;
			}
		}
        //如果此时的事务传播行为为PROPAGATION_NESTED,
		if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
		    //不支持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() + "]");
			}
			//默认是true,如果使用的是JtaTransactionManager,返回false
			if (useSavepointForNestedTransaction()) {
                //使用已存在事务对象返回
				DefaultTransactionStatus status =
						prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
				status.createAndHoldSavepoint();
				return status;
			}
			else {
			//重新开启事务
				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.
		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);
	}

以上代码的注释和之前的事务传播类型的表格一致,还是一步步分析如何挂起事务和如何重新开启事务,挂起事务:

	protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException {
		if (TransactionSynchronizationManager.isSynchronizationActive()) {
			List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();
			try {
				Object suspendedResources = null;
				if (transaction != null) {
					suspendedResources = doSuspend(transaction);
				}
				String name = TransactionSynchronizationManager.getCurrentTransactionName();
				TransactionSynchronizationManager.setCurrentTransactionName(null);
				boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
				TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);
				Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
				TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);
				boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive();
				TransactionSynchronizationManager.setActualTransactionActive(false);
				return new SuspendedResourcesHolder(
						suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);
			}
			catch (RuntimeException | Error ex) {
				// doSuspend failed - original transaction is still active...
				doResumeSynchronization(suspendedSynchronizations);
				throw ex;
			}
		}
		else if (transaction != null) {
			// Transaction active but no synchronization active.
			Object suspendedResources = doSuspend(transaction);
			return new SuspendedResourcesHolder(suspendedResources);
		}
		else {
			// Neither transaction nor synchronization active.
			return null;
		}
	}

核心方法doSuspend:

    protected Object doSuspend(Object transaction) {
        DataSourceTransactionManager.DataSourceTransactionObject txObject = (DataSourceTransactionManager.DataSourceTransactionObject)transaction;
        //清空当前事务对象的ConnectionHolder
        txObject.setConnectionHolder((ConnectionHolder)null);
        return TransactionSynchronizationManager.unbindResource(this.obtainDataSource());
    }

这里没什么说的,就是清空相关的值;再看下doBegin,开启新事务:

    protected void doBegin(Object transaction, TransactionDefinition definition) {
        DataSourceTransactionManager.DataSourceTransactionObject txObject = (DataSourceTransactionManager.DataSourceTransactionObject)transaction;
        Connection con = null;

        try {
            if (!txObject.hasConnectionHolder() || txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
                Connection newCon = this.obtainDataSource().getConnection();
                if (this.logger.isDebugEnabled()) {
                    this.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);
            if (con.getAutoCommit()) {
                txObject.setMustRestoreAutoCommit(true);
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
                }

                con.setAutoCommit(false);
            }

            this.prepareTransactionalConnection(con, definition);
            txObject.getConnectionHolder().setTransactionActive(true);
            int timeout = this.determineTimeout(definition);
            if (timeout != -1) {
                txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
            }

            if (txObject.isNewConnectionHolder()) {
                TransactionSynchronizationManager.bindResource(this.obtainDataSource(), txObject.getConnectionHolder());
            }

        } catch (Throwable var7) {
            if (txObject.isNewConnectionHolder()) {
                DataSourceUtils.releaseConnection(con, this.obtainDataSource());
                txObject.setConnectionHolder((ConnectionHolder)null, false);
            }

            throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", var7);
        }
    }

总结,开启一个新的连接,并封装到txObject中去;事务已存在的情况分析完,我们看下事务不存在的情况:

// No existing transaction found -> check propagation behavior to find out how to proceed.
//事务不存在且事务传播行为为PROPAGATION_MANDATORY,抛出异常
		if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
			throw new IllegalTransactionStateException(
					"No existing transaction found for transaction marked with propagation 'mandatory'");
		}
		else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
				definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
				definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
			SuspendedResourcesHolder suspendedResources = suspend(null);
			if (debugEnabled) {
				logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
			}
			try {
				boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
				DefaultTransactionStatus status = newTransactionStatus(
						definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
				doBegin(transaction, definition);
				prepareSynchronization(status, definition);
				return status;
			}
			catch (RuntimeException | Error ex) {
				resume(null, suspendedResources);
				throw ex;
			}
		}
		else {
			// Create "empty" transaction: no actual transaction, but potentially synchronization.
			if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
				logger.warn("Custom isolation level specified but no actual transaction initiated; " +
						"isolation level will effectively be ignored: " + definition);
			}

当事务传播行为为PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW、PROPAGATION_NESTED时,新建事务,doBegin方法上面分析了,就是新建一个数据源的连接;此时返回一个DefaultTransactionStatus

本项目是一个基于SSM(Spring+SpringMVC+MyBatis)框架和Vue.js前端技术的家教平台系统。该系统旨在为家教和学生提供一个便捷、高效的在线交流和预约平台,涵盖了从用户注册登录、个人信息管理、课程发布与搜索、预约与取消预约、评价反馈等一系列功能。 在后台管理方面,系统提供了管理员对用户信息、课程信息、预约记录等进行管理的功能,确保平台的正常运行和数据的准确性。通过Spring框架的依赖注入和AOP特性,实现了业务逻辑的清晰分离和高效处理;SpringMVC则负责处理前端请求和响应,提供友好的用户界面;MyBatis作为ORM框架,简化了数据库操作,提高了数据访问的效率和安全性。 前端部分采用Vue.js框架,结合Vue Router进行页面路由管理,Axios进行HTTP请求,实现了前后端分离的开发模式。Vue.js的组件化开发和响应式数据绑定特性,使得前端页面更加动态和交互性强,提升了用户体验。 数据库设计采用了MySQL,存储了用户信息、课程信息、预约记录等核心数据。通过合理的数据库表结构和索引设计,保证了系统的高效运行和数据的一致性。 该项目不仅适合计算机相关专业的毕设学生参考和学习,也适合Java学习者进行项目实战练习。通过对该项目的深入理解和二次开发,可以实现更多个性化功能,进一步提升技术水平和实践能力。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值