Spring的编程式事务管理

编程式事务

Spring 事务管理分为编程式和声明式的两种方式。编程式事务指的是通过编码方式实现事务;声明式事务基于 AOP,将具体业务逻辑与事务处理解耦,如常见的基于 @Transactional 注解的方式。本文将着重介绍基于TransactionTemplate的编程式事务管理。

基于TransactionTemplate

核心内容

核心方法源代码

public class TransactionTemplate extends DefaultTransactionDefinition
		implements TransactionOperations, InitializingBean {

	/** Logger available to subclasses. */
	protected final Log logger = LogFactory.getLog(getClass());

	@Nullable
	private PlatformTransactionManager transactionManager;


	/**
	 * Construct a new TransactionTemplate for bean usage.
	 * <p>Note: The PlatformTransactionManager needs to be set before
	 * any {@code execute} calls.
	 * @see #setTransactionManager
	 */
	public TransactionTemplate() {
	}

	/**
	 * Construct a new TransactionTemplate using the given transaction manager.
	 * @param transactionManager the transaction management strategy to be used
	 */
	public TransactionTemplate(PlatformTransactionManager transactionManager) {
		this.transactionManager = transactionManager;
	}

	/**
	 * Construct a new TransactionTemplate using the given transaction manager,
	 * taking its default settings from the given transaction definition.
	 * @param transactionManager the transaction management strategy to be used
	 * @param transactionDefinition the transaction definition to copy the
	 * default settings from. Local properties can still be set to change values.
	 */
	public TransactionTemplate(PlatformTransactionManager transactionManager, TransactionDefinition transactionDefinition) {
		super(transactionDefinition);
		this.transactionManager = transactionManager;
	}


	/**
	 * Set the transaction management strategy to be used.
	 */
	public void setTransactionManager(@Nullable PlatformTransactionManager transactionManager) {
		this.transactionManager = transactionManager;
	}

	/**
	 * Return the transaction management strategy to be used.
	 */
	@Nullable
	public PlatformTransactionManager getTransactionManager() {
		return this.transactionManager;
	}

	@Override
	public void afterPropertiesSet() {
		if (this.transactionManager == null) {
			throw new IllegalArgumentException("Property 'transactionManager' is required");
		}
	}


	@Override
	@Nullable
	public <T> T execute(TransactionCallback<T> action) throws TransactionException {
		Assert.state(this.transactionManager != null, "No PlatformTransactionManager set");

		if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {
			return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action);
		}
		else {
			TransactionStatus status = this.transactionManager.getTransaction(this);
			T result;
			try {
				result = action.doInTransaction(status);
			}
			catch (RuntimeException | Error ex) {
				// Transactional code threw application exception -> rollback
				rollbackOnException(status, ex);
				throw ex;
			}
			catch (Throwable ex) {
				// Transactional code threw unexpected exception -> rollback
				rollbackOnException(status, ex);
				throw new UndeclaredThrowableException(ex, "TransactionCallback threw undeclared checked exception");
			}
			this.transactionManager.commit(status);
			return result;
		}
	}

	/**
	 * Perform a rollback, handling rollback exceptions properly.
	 * @param status object representing the transaction
	 * @param ex the thrown application exception or error
	 * @throws TransactionException in case of a rollback error
	 */
	private void rollbackOnException(TransactionStatus status, Throwable ex) throws TransactionException {
		Assert.state(this.transactionManager != null, "No PlatformTransactionManager set");

		logger.debug("Initiating transaction rollback on application exception", ex);
		try {
			this.transactionManager.rollback(status);
		}
		catch (TransactionSystemException ex2) {
			logger.error("Application exception overridden by rollback exception", ex);
			ex2.initApplicationException(ex);
			throw ex2;
		}
		catch (RuntimeException | Error ex2) {
			logger.error("Application exception overridden by rollback exception", ex);
			throw ex2;
		}
	}


	@Override
	public boolean equals(@Nullable Object other) {
		return (this == other || (super.equals(other) && (!(other instanceof TransactionTemplate) ||
				getTransactionManager() == ((TransactionTemplate) other).getTransactionManager())));
	}

}

从上面代码可以看到 TransactionTemplate 实现了 TransactionOperations接口

public interface TransactionOperations {

	@Nullable
	<T> T execute(TransactionCallback<T> action) throws TransactionException;

	default void executeWithoutResult(Consumer<TransactionStatus> action) throws TransactionException {
		execute(status -> {
			action.accept(status);
			return null;
		});
	}
	static TransactionOperations withoutTransaction() {
		return WithoutTransactionOperations.INSTANCE;
	}

}

而这个类有一个虚拟的扩展方法 executeWithoutResult ,这个方法适用于
执行一段简单的事务操作,不需要从回调返回对象或访问,并且可以方便的使用Lambda表达式。

无回调方法的使用
 @Autowired
 private TransactionTemplate transactionTemplate;
transactionTemplate.executeWithoutResult(t -> {
	//这里写事务方法
	a.insert(b);
});

再来看另一个方法 execute(),方法参数 TransactionCallback 里有一个方法

@FunctionalInterface
public interface TransactionCallback<T> {
	@Nullable
	T doInTransaction(TransactionStatus status);

}

实现此接口的抽象类

public abstract class TransactionCallbackWithoutResult implements TransactionCallback<Object> {

	@Override
	@Nullable
	public final Object doInTransaction(TransactionStatus status) {
		doInTransactionWithoutResult(status);
		return null;
	}
	protected abstract void doInTransactionWithoutResult(TransactionStatus status);

}

可以看出 TransactionTemplate 的 execute 方法提供一个内部匿名类,用来写事物代码,然后提供一个TransactionStatus的 参数,用来控制回滚。

  • TransactionTemplate.execute( … )执行事务管理的时候,传入的参数有两种选择:

     1. TransactionCallback  //有返回值
     2. TransactionCallbackWithoutResult  //无返回值
    
有回调方法的使用

先注入模板类

 @Autowired
 private TransactionTemplate transactionTemplate;
  1. 带返回值-TransactionCallback
public Object xxx() {
        transactionTemplate.execute(new TransactionCallback() {
            @Override
            public Object doInTransaction(TransactionStatus transactionStatus) {
				Object result;
                try {
                    // ... 事务方法
                    result = new Object()return result;
                } catch (Exception e) {
                    //回滚
                    transactionStatus.setRollbackOnly();
                    result = false;
                    return result;
                }
            }
        });
}

//lamada 写法
public Object xxx() {
	transactionTemplate.execute(transactionStatus->{
				try {
                    // ... 事务方法
                    result = new Object()return result;
                } catch (Exception e) {
                    //回滚
                    transactionStatus.setRollbackOnly();
                    result = false;
                    return result;
                }
	});

}

2.无返回值-TransactionCallbackWithoutResult

public void xxx() {

        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {

                try {

                    // ... 事务方法
                } catch (Exception e){
                    //回滚
                    transactionStatus.setRollbackOnly();
                }

            }
        });
}

注: 事务方法可以不用显式的使用try,catch,手动回滚。TransactionTemplate会在遇到错误的时候自动回滚,不需要使用try,catch,适用于不需要捕获异常的场景。

transactionTemplate.execute(transactionStatus->{
			//直接写业务代码,出现异常会自动回滚
	});
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值