spring事务二编程式事务


二、编程式事务xml的配置


基于 TransactionTemplate 的编程式事务管理



现在就可以在Spring管理的Bean中注入并使用:

[java]  view plain  copy
  1. @ContextConfiguration(locations = {"classpath:applicationContext.xml"})  
  2. @RunWith(SpringJUnit4ClassRunner.class)  
  3. public class TransactionTest {  
  4.   
  5.     private final Logger logger = LoggerFactory.getLogger(TransactionTest.class);  
  6.   
  7.     @Resource  
  8.     private TransactionTemplate transactionTemplate;  
  9.   
  10.     @Test  
  11.     public void testProgrammaticTransaction() {  
  12.         logger.info("Begin test programmatic transaction!########################");  
  13.         // 第一个事务  
  14.         Integer result = transactionTemplate.execute(new TransactionCallback<Integer>() {  
  15.             @Override  
  16.             public Integer doInTransaction(TransactionStatus status) {  
  17.                 logger.info("Do in transaction with a return value!#####################################");  
  18.                 // 在事务中执行, 有返回值  
  19.                 return 1;  
  20.             }  
  21.         });  
  22.   
  23.         logger.info("result:{}", result);  
  24.   
  25.         // 第二个事务  
  26.         transactionTemplate.execute(new TransactionCallbackWithoutResult() {  
  27.             @Override  
  28.             protected void doInTransactionWithoutResult(TransactionStatus status) {  
  29.                 logger.info("Do in transaction without a return value!#####################################");  
  30.                 // 在事务中执行,没有返回值  
  31.             }  
  32.         });  
  33.     }  

看到TransactionTemplate的使用比较简单,只需将需要在事务中之行的逻辑封装成TransactionCallback<T>,这个是带返回值的,不带返回值的封装成TransactionCallbackWithoutResult。

观察下事务的执行情况,事务work了。



看下它的核心代码:

[java]  view plain  copy
  1. @Override  
  2.     public <T> T execute(TransactionCallback<T> action) throws TransactionException {  
  3.         if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {  
  4.             return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action);  
  5.         }  
  6.         else {  
  7.             TransactionStatus status = this.transactionManager.getTransaction(this);  
  8.             T result;  
  9.             try {  
  10.                 result = action.doInTransaction(status);  
  11.             }  
  12.             catch (RuntimeException ex) {  
  13.                 // Transactional code threw application exception -> rollback  
  14.                 rollbackOnException(status, ex);  
  15.                 throw ex;  
  16.             }  
  17.             catch (Error err) {  
  18.                 // Transactional code threw error -> rollback  
  19.                 rollbackOnException(status, err);  
  20.                 throw err;  
  21.             }  
  22.             catch (Exception ex) {  
  23.                 // Transactional code threw unexpected exception -> rollback  
  24.                 rollbackOnException(status, ex);  
  25.                 throw new UndeclaredThrowableException(ex, "TransactionCallback threw undeclared checked exception");  
  26.             }  
  27.             this.transactionManager.commit(status);  
  28.             return result;  
  29.         }  
  30.     }  

需要执行事务的业务逻辑被封装成action,它所做的也很简单,在action执行前后进行事务的开启和提交(或着rollback)。开启事务时需要transactionManager的getTransaction方法获取TransactionStatus,而这个方法的参数是TransactionDefinition,前面说过TransactionTemplate本身就是TransactionDefinition的实现,所以将this作为参数传递给这个方法就可以。

也可以看到,TransactionTemplate和基于AOP的配置一样,也是在方法前后执行事务的开启和提交,只是实现的方式改变了。

TransactionTemplate 的 execute() 方法有一个 TransactionCallback 类型的参数,该接口中定义了一个 doInTransaction() 方法,通常我们以匿名内部类的方式实现 TransactionCallback 接口,并在其 doInTransaction() 方法中书写业务逻辑代码。这里可以使用默认的事务提交和回滚规则,这样在业务代码中就不需要显式调用任何事务管理的 API。doInTransaction() 方法有一个TransactionStatus 类型的参数,我们可以在方法的任何位置调用该参数的 setRollbackOnly() 方法将事务标识为回滚的,以执行事务回滚。

根据默认规则,如果在执行回调方法的过程中抛出了未检查异常,或者显式调用了TransacationStatus.setRollbackOnly() 方法,则回滚事务;如果事务执行完成或者抛出了 checked 类型的异常,则提交事务。

TransactionCallback 接口有一个子接口 TransactionCallbackWithoutResult,该接口中定义了一个 doInTransactionWithoutResult() 方法,TransactionCallbackWithoutResult 接口主要用于事务过程中不需要返回值的情况。当然,对于不需要返回值的情况,我们仍然可以使用 TransactionCallback 接口,并在方法中返回任意值即可。

基于底层 API 的编程式事务管理

根据PlatformTransactionManager、TransactionDefinition 和 TransactionStatus 三个核心接口,我们完全可以通过编程的方式来进行事务管理。示例代码如清单4所示:

@Autowired
private PlatformTransactionManager transactionManager;

// 此处启用编程式事务,是为了保证try里的数据一致
TransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = transactionManager.getTransaction(def);  
try {
/**
* 如果使用第三方支付的同时还使用了钱包的某项补贴消费了,要去钱包扣减这项补贴,并且添加相应的补贴流水
*/
String orderIdPrefix = CfgHelper.getValue(Constants.orderId_prefix);
log.error("paymentserviceimpl l来到这里了========================orderIdPrefix"+orderIdPrefix);
if (null != order.getTags() && order.getTags().trim().equals("CONSUME_SUBSIDY")) {
log.info("处理本次订单的交易的服务为:" + orderIdPrefix + ",订单号:" + orderId + ",处理时间:" + System.currentTimeMillis());
log.error("处理本次订单的交易的服务为:" + orderIdPrefix + ",订单号:" + orderId + ",处理时间:" + System.currentTimeMillis());
newWalletPayment(order.getUserId(), orderId, order.getDeductionPrice(), PaymentMethodEnum.CONSUME.getValue());
} else if (null != order.getTags() && order.getTags().trim().equals("HT_SUBSIDY")) {
log.info("处理本次订单的交易的服务为:" + orderIdPrefix + ",订单号:" + orderId + ",处理时间:" + System.currentTimeMillis());
newWalletPayment(order.getUserId(), orderId, order.getDeductionPrice(), PaymentMethodEnum.HTSUBSIDY.getValue());
log.error("处理本次订单的交易的服务为:" + orderIdPrefix + ",订单号:" + orderId + ",处理时间:" + System.currentTimeMillis());
}
log.error("更新订单状态即将=======:" + order + ",order.getDmId()号:" +  order.getDmId() + ",payType时间:" + payType+"threeSerialNumber"+threeSerialNumber);
rechargeSeller(order, order.getDmId() + "", payType, threeSerialNumber);
log.error("回来了============================================");
transactionManager.commit(status);
} catch (Exception e) {
e.printStackTrace();
log.error("用户:" + order.getUserId() + ",订单:" + orderId + ",抛出异常,事务回滚." + e.getMessage());
transactionManager.rollback(status);
throw new ServiceException("用户:" + order.getUserId() + ",订单:" + orderId + "修改钱包和添加补贴流水异常." + e.getMessage(), e);
}

如上所示,我们在类中增加了两个属性:一个是 TransactionDefinition 类型的属性,它用于定义一个事务;另一个是 PlatformTransactionManager 类型的属性,用于执行事务管理操作。

如果方法需要实施事务管理,我们首先需要在方法开始执行前启动一个事务,调用PlatformTransactionManager.getTransaction(...) 方法便可启动一个事务。创建并启动了事务之后,便可以开始编写业务逻辑代码,然后在适当的地方执行事务的提交或者回滚。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值