zoukankan      html  css  js  c++  java
  • Spring事务管理的另一种方式--TransactionTemplate编程式事务管理简单入门 1,

    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 }  
     
     
     
     
     
    复制代码
     
     
     
  • 相关阅读:
    Python爬虫入门教程 15-100 石家庄政民互动数据爬取
    mysql 1449 : The user specified as a definer ('root'@'%') does not exist 解决方法
    python cx_Oracle 自动重连
    oracle删除日志文件
    oracle删除日志文件
    oracle删除日志文件
    oracle删除日志文件
    git 常用操作总结
    git 常用操作总结
    git 常用操作总结
  • 原文地址:https://www.cnblogs.com/smallfa/p/14028884.html
Copyright © 2011-2022 走看看