您的位置:首页 > 编程语言 > Java开发

Spring事务管理的另一种方式--TransactionTemplate编程式事务管理简单入门

2017-06-05 14:44 447 查看
1, 一直以来, 在用Spring进行事物管理时, 只知道用声明式的策略, 即根据不同的数据源, 配置一个事物管理器(TransactionManager), 通过配置切面(PointCut)应用到相应的业务方法上或者直接在方法上加@Ttransactional注解.

  这种事务管理使用起来比较简单,但个人感觉灵活性欠缺了点.

2, 最近看公司项目代码, 发现有位同事在他的模块了用了另外一种事务管理方式, 查了一下,TransactionTemplate是编程式事务管理.需要自己手动在每个业务方法中实现事务.

3, TransactionTemplate使用(不一定全面):

  A, 在DAO层的配置文件中, 配置TransactionTemplate, 需要注入TransactionManager

  

<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>

<bean id="transactionTemplate"
class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
</bean>


B, 将TransactionTemplate注入到业务层方法中, 并使用:

  首先分析一下TransactionTemplate的核心原理:

  TransactionTemplate核心方法:

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


由上面的代码可以推测到, 真正执行业务方法的关键代码是: action.doInTransaction(status);

正好, 有个入参TransactionCallback<T>, 翻看该接口的源码:

1 public interface TransactionCallback<T> {
2
5     T doInTransaction(TransactionStatus status);
6
7 }


该接口只有一个doInTransaction方法, 那么很简单, 我们可以通过匿名内部类的方式将业务代码放在doInTransaction中:

举例如下:

1 private PayOrderDAO payOrderDAO;
2
3 protected TransactionTemplate transactionTemplate;
4
5 /**
6  * 保存支付订单
7  */
8 protected PayOrder savePayReq(final PayOrder payOrder) {
9
10     @Autowired
11     private TransactionTemplate transactionTemplate;
12
13      @Autowired
14     private PayOrderDAO payOrderDAO;
15
16     PayOrder order = (PayOrder) this.transactionTemplate
17             .execute(new TransactionCallback() {
18                 @Override
19                 public Object doInTransaction(TransactionStatus status) {
20                     // 查看是否已经存在支付订单,如果已经存在则返回订单主键
21                     PayOrder payOrderTemp = payOrderDAO.findOrder(String
22                             .valueOf(payOrder.getPayOrderId()));
23
24                     // 由支付渠道类型(PayChannelType)转换得到交易类型(PayType)
25                     if (payOrder.getPayChannelId().equalsIgnoreCase(PAY_CHNL_ACT_BAL)) {// 账户余额支付
26                         payOrder.setPayType("3");
27                     } else if (payOrder.getPayChannelId().equalsIgnoreCase(PAY_CHNL_FAST_PAY)) {// 联通快捷支付
28                         payOrder.setPayType("4");
29                     } else {// 网银网关支付
30                         payOrder.setPayType("2");
31                     }
32
33                     // 比对新的支付金额与原订单金额是否一致,如不一致则提示错误
34                     if (payOrderTemp == null) {
35                         String orderId = payOrderDAO.save(payOrder);
36                         payOrder.setPayOrderId(orderId);
37                         return payOrder;
38                     } else {
39                         return payOrderTemp;
40                     }
41                 }
42             });
43     if ("2".equals(order.getOrderState())) {// 2:表示支付成功
44         throw new EpaymentBizException(StatusCode.DQSystem.PAY_FAIL,
45                 "同一订单不能重复支付");
46     } else if (payOrder.getPayAmt().longValue() != order.getPayAmt()
47             .longValue()) {
48         throw new EpaymentBizException(StatusCode.DQSystem.PAY_FAIL,
49                 "交易金额与原订单不一致");
50     } else {
51         return payOrder;
52     }
53
54 }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐