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

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

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

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

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

  

  1. <bean id="transactionManager"
  2. class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  3. <property name="dataSource" ref="dataSource"/>
  4. </bean>
  5.  
  6. <bean id="transactionTemplate"
  7. class="org.springframework.transaction.support.TransactionTemplate">
  8. <property name="transactionManager">
  9. <ref bean="transactionManager"/>
  10. </property>
  11. </bean>

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

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

  TransactionTemplate核心方法:

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

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

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

  1. public interface TransactionCallback<T> {
  2.  
  3. T doInTransaction(TransactionStatus status);
  4.  
  5. }

该接口只有一个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. }

Spring事务管理的另一种方式--TransactionTemplate编程式事务管理简单入门的更多相关文章

  1. Spring事务管理的实现方式:编程式事务与声明式事务

    1.上篇文章讲解了Spring事务的传播级别与隔离级别,以及分布式事务的简单配置,点击回看上篇文章 2.编程式事务:编码方式实现事务管理(代码演示为JDBC事务管理) Spring实现编程式事务,依赖 ...

  2. Spring事务管理的实现方式之编程式事务与声明式事务详解

    原创说明:本博文为原创作品,绝非他处转载,转载请联系博主 1.上篇文章讲解了Spring事务的传播级别与隔离级别,以及分布式事务的简单配置,点击回看上篇文章 2.编程式事务:编码方式实现事务管理(代码 ...

  3. Spring事务管理实现方式之编程式事务与声明式事务详解(转)

    原文:https://blog.csdn.net/liaohaojian/article/details/70139151 编程式事务 编码方式实现事务管理(代码演示为JDBC事务管理) Spring ...

  4. 深入理解TransactionTemplate编程式事务

    Spring可以支持编程式事务和声明式事务. Spring提供的最原始的事务管理方式是基于TransactionDefinition.PlatformTransactionManager.Transa ...

  5. TransactionTemplate编程式事务管理方式的进阶使用---自定义拓展模板类

    1, 前面一篇的文章介绍了TransactionTemplate的基本使用方法. 同事在其基础上又做了一层封装,这样更贴合本公司的业务与规范. 2, 首先定义了两个接口: ServiceTemplat ...

  6. Spring的编程式事务和声明式事务

    事务管理对于企业应用来说是至关重要的,当出现异常情况时,它也可以保证数据的一致性. Spring事务管理的两种方式 spring支持编程式事务管理和声明式事务管理两种方式. 编程式事务使用Transa ...

  7. spring的声明式事务和编程式事务

    事务管理对于企业应用来说是至关重要的,当出现异常情况时,它可以保证数据的一致性. Spring事务管理的两种方式 1.编程式事务 使用Transaction Ttempleate或者直接使用底层的Pl ...

  8. Spring事务:一种编程式事务,三种声明式事务

    事务隔离级别 隔离级别是指若干个并发的事务之间的隔离程度.TransactionDefinition 接口中定义了五个表示隔离级别的常量: TransactionDefinition.ISOLATIO ...

  9. 春天的事务之9.3编程式事务 - 跟我学spring3

    9.3编程式事务 9.3.1编程式事务概述 所谓编程式事务指的是通过编码方式实现事务,即类似于JDBC编程实现事务管理. Spring框架提供一致的事务抽象,因此对于JDBC还是JTA事务都是采用相同 ...

随机推荐

  1. 一步一步教你将开源项目上传到jcenter

    最近闲着看了一下jcenter的使用,也想将自己使用频率比较高的东西抽成类库,然后通过compile来使用,提高开发效率,本来以为挺简单的,但是网上介绍的比较模糊,很多博客也比较老了,不适用,花了我一 ...

  2. 为什么使用bootstrap在一个页面同时做两个轮播效果时,只有第一个有效??

    我们都知道使用bootstrap做轮播效果非常快,但是有时候一个页面会需要两个轮播:但这个时候再次使用bootstrap做轮播效果时就会失效:原因在于bootstrap的Carousel问题,只要修改 ...

  3. WPF: 实现 ScrollViewer 滚动到指定控件处

    在前端 UI 开发中,有时,我们会遇到这样的需求:在一个 ScrollViewer 中有很多内容,而我们需要实现在执行某个操作后能够定位到其中指定的控件处:这很像在 HTML 页面中点击一个链接后定位 ...

  4. 小发现之location.search与location.hash问题

    背景 用过Vue Router的童鞋应该对路由传参的方式多多少少有些印象,Vue Router支持两种传参方式:query与params:其中query方式就是动态地在路由url后面追加参数,就是ht ...

  5. java web数据库(SQL 2008+IDEA 14)环境配置

    废话少说,在之前已经配置过IDEA+Tomcat的环境之后,现在需要进行数据库配置: 1.首先,SQL SERVER2008数据库的安装 (1)将下载的sqlserver 2008数据库进行解压,点击 ...

  6. Jmeter-BeanShell PostProcessor提取请求及响应结果并保存到本地文件

    1.新建一个本地csv文件,存放请求需要使用的变量值account,password,并配置CSV Data Set Config 2.添加一个HTTP请求 3.添加正则提取器用来提取响应结果中的re ...

  7. 【PHP】最详细PHP从入门到精通(四)——PHP中的字符串

     PHP从入门到精通 之PHP中的字符串 大家好,继续跟进PHP最详尽的知识更新,本周,跟大家重点讲一下PHP中字符串的使用.在PHP中,字符串是非常重要的一个概念,基本上大家想到的字符串的处理功能, ...

  8. git视频教程

    git 精简版视频教程-2小时快速入门精华版,小教程很快就可以看完. 旺旺 QQ:Git是目前世界上最先进的分布式版本控制系统(没有之一). Git有非常高的逼格,简单来说就是:高端大气上档次. 这么 ...

  9. .net core web api + Autofac + EFCore 个人实践

    1.背景 去年时候,写过一篇<Vue2.0 + Element-UI + WebAPI实践:简易个人记账系统>,采用Asp.net Web API + Element-UI.当时主要是为了 ...

  10. 【LeetCode】327. Count of Range Sum

    题目: Given an integer array nums, return the number of range sums that lie in [lower, upper] inclusiv ...