Spring事務管理的另一種方式--TransactionTemplate編程式事務管理簡單入門


Spring事務管理的另一種方式--TransactionTemplate編程式事務管理簡單入門

 

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 }  
復制代碼

轉自:https://www.cnblogs.com/wyisprogramming/p/6944878.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM