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核心方法:

 public class TransactionTemplate extends DefaultTransactionDefinition
implements TransactionOperations, InitializingBean { public <T> T execute(TransactionCallback<T> action) throws TransactionException {
if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {
return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action);
}
else {
TransactionStatus status = this.transactionManager.getTransaction(this);
T result;
try {
result = action.doInTransaction(status);
}
catch (RuntimeException ex) {
// Transactional code threw application exception -> rollback
rollbackOnException(status, ex);
throw ex;
}
catch (Error err) {
// Transactional code threw error -> rollback
rollbackOnException(status, err);
throw err;
}
catch (Exception ex) {
// Transactional code threw unexpected exception -> rollback
rollbackOnException(status, ex);
throw new UndeclaredThrowableException(ex, "TransactionCallback threw undeclared checked exception");
}
this.transactionManager.commit(status);
return result;
}
}

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

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

 public interface TransactionCallback<T> {

     T doInTransaction(TransactionStatus status);

 }

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

举例如下:

 private PayOrderDAO payOrderDAO;  

 protected TransactionTemplate transactionTemplate;  

 /**
* 保存支付订单
*/
protected PayOrder savePayReq(final PayOrder payOrder) { @Autowired
private TransactionTemplate transactionTemplate; @Autowired
private PayOrderDAO payOrderDAO; PayOrder order = (PayOrder) this.transactionTemplate
.execute(new TransactionCallback() {
@Override
public Object doInTransaction(TransactionStatus status) {
// 查看是否已经存在支付订单,如果已经存在则返回订单主键
PayOrder payOrderTemp = payOrderDAO.findOrder(String
.valueOf(payOrder.getPayOrderId())); // 由支付渠道类型(PayChannelType)转换得到交易类型(PayType)
if (payOrder.getPayChannelId().equalsIgnoreCase(PAY_CHNL_ACT_BAL)) {// 账户余额支付
payOrder.setPayType("3");
} else if (payOrder.getPayChannelId().equalsIgnoreCase(PAY_CHNL_FAST_PAY)) {// 联通快捷支付
payOrder.setPayType("4");
} else {// 网银网关支付
payOrder.setPayType("2");
} // 比对新的支付金额与原订单金额是否一致,如不一致则提示错误
if (payOrderTemp == null) {
String orderId = payOrderDAO.save(payOrder);
payOrder.setPayOrderId(orderId);
return payOrder;
} else {
return payOrderTemp;
}
}
});
if ("2".equals(order.getOrderState())) {// 2:表示支付成功
throw new EpaymentBizException(StatusCode.DQSystem.PAY_FAIL,
"同一订单不能重复支付");
} else if (payOrder.getPayAmt().longValue() != order.getPayAmt()
.longValue()) {
throw new EpaymentBizException(StatusCode.DQSystem.PAY_FAIL,
"交易金额与原订单不一致");
} else {
return payOrder;
} }

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. grid编辑后时间格式不对问题

    在column中应该定义xtype和format格式: xtype: 'datecolumn', format:'Y-m-d'   之后正常

  2. Wowza 部署 安装 配置 测试 直播

    下载,最好用快的IP下好后传到需要的节点上,下面链接不能下载的情况下百度谷歌必应找资源,jdk旧版在oracle需登录方可下载 JDK1.6 wget -c http://dl.download.cs ...

  3. python 标准库 -- pickle & cPickle

    pickle & cPickle pickle 和 cPickle 除了导入名称不一样之外, 使用方法, 均一样. pickle 导入 import pickle cPickle 导入 imp ...

  4. centos 6.6 ios镜像文件 下载 官网和阿里云两种方式教你下载

    1百度一下:centos 打开打开官网.选择这一项 CET CENTOS 2选择 DVD ISO,双击下载 直接选择左键点击下载 这里需要迅雷 方法 二 打开 https://mirrors.aliy ...

  5. [编织消息框架][netty源码分析]8 Channel 实现类NioSocketChannel职责与实现

    Unsafe是托委访问socket,那么Channel是直接提供给开发者使用的 Channel 主要有两个实现 NioServerSocketChannel同NioSocketChannel 致于其它 ...

  6. 在 Mac OS 上编译 FFmpeg

    本文转自:在 Mac OS 上编译 FFmpeg | www.samirchen.com 安装 Xcode 和 Command Line Tools 从 App Store 上安装 Xcode,并确保 ...

  7. python爬虫从入门到放弃前奏之学习方法

    首谈方法 最近在整理爬虫系列的博客,但是当整理几篇之后,发现一个问题,不管学习任何内容,其实方法是最重要的,按照我之前写的博客内容,其实学起来还是很点枯燥不能解决传统学习过程中的几个问题: 这个是普通 ...

  8. jquery删除表格行

    $(".mingxirmspan").click(function(){ $(this).closest("tr").remove(); })

  9. 1.免费安装myeclipse 10以及破解

    1.材料准备 jdk1.8.0_101 网盘地址链接: http://pan.baidu.com/s/1ge8Jaz5 密码: qb6v myeclipse-10.6-offline-installe ...

  10. SQL SERVER查看索引使用情况

    SELECT DISTINCT DB_NAME() AS N'db_name' , E.name AS N'schema_name' , OBJECT_NAME(a.object_id) AS N't ...