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核心方法:
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编程式事务管理简单入门的更多相关文章
- Spring事务管理的实现方式:编程式事务与声明式事务
1.上篇文章讲解了Spring事务的传播级别与隔离级别,以及分布式事务的简单配置,点击回看上篇文章 2.编程式事务:编码方式实现事务管理(代码演示为JDBC事务管理) Spring实现编程式事务,依赖 ...
- Spring事务管理的实现方式之编程式事务与声明式事务详解
原创说明:本博文为原创作品,绝非他处转载,转载请联系博主 1.上篇文章讲解了Spring事务的传播级别与隔离级别,以及分布式事务的简单配置,点击回看上篇文章 2.编程式事务:编码方式实现事务管理(代码 ...
- Spring事务管理实现方式之编程式事务与声明式事务详解(转)
原文:https://blog.csdn.net/liaohaojian/article/details/70139151 编程式事务 编码方式实现事务管理(代码演示为JDBC事务管理) Spring ...
- 深入理解TransactionTemplate编程式事务
Spring可以支持编程式事务和声明式事务. Spring提供的最原始的事务管理方式是基于TransactionDefinition.PlatformTransactionManager.Transa ...
- TransactionTemplate编程式事务管理方式的进阶使用---自定义拓展模板类
1, 前面一篇的文章介绍了TransactionTemplate的基本使用方法. 同事在其基础上又做了一层封装,这样更贴合本公司的业务与规范. 2, 首先定义了两个接口: ServiceTemplat ...
- Spring的编程式事务和声明式事务
事务管理对于企业应用来说是至关重要的,当出现异常情况时,它也可以保证数据的一致性. Spring事务管理的两种方式 spring支持编程式事务管理和声明式事务管理两种方式. 编程式事务使用Transa ...
- spring的声明式事务和编程式事务
事务管理对于企业应用来说是至关重要的,当出现异常情况时,它可以保证数据的一致性. Spring事务管理的两种方式 1.编程式事务 使用Transaction Ttempleate或者直接使用底层的Pl ...
- Spring事务:一种编程式事务,三种声明式事务
事务隔离级别 隔离级别是指若干个并发的事务之间的隔离程度.TransactionDefinition 接口中定义了五个表示隔离级别的常量: TransactionDefinition.ISOLATIO ...
- 春天的事务之9.3编程式事务 - 跟我学spring3
9.3编程式事务 9.3.1编程式事务概述 所谓编程式事务指的是通过编码方式实现事务,即类似于JDBC编程实现事务管理. Spring框架提供一致的事务抽象,因此对于JDBC还是JTA事务都是采用相同 ...
随机推荐
- 第二章完结,包含exam练习
正则方程(Normal Equation) 梯度下降是最小化代价函数\(J(\theta)\)的一种方式,这里提出了另一种方式即正则方式不使用迭代方式:\(\theta = (X^TX)^{-1}X^ ...
- jquery水平导航菜单展示
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 国内互联网公司github网址
-----------------------------------------------------推荐技术------------------------------------------- ...
- 几种MQ消息队列对比与消息队列之间的通信问题
消息队列 开发语言 协议支持 设计模式 持久化支持 事务支持 负载均衡支持 功能特点 缺点 RabbitMQ Erlang AMQP,XMPP,SMTP,STOMP 代理(Broker)模式(消息在发 ...
- Pycharm创建的virtualenv环境缺失pip.exe的问题(Windows系统)
Windows环境: 1. Python安装在d:\Python\Python35下, Python新版本安装时默认会勾选pip功能 2. PyCharm的Settings中Create Virtua ...
- [leetcode-630-Course Schedule III]
There are n different online courses numbered from 1 to n. Each course has some duration(course leng ...
- python迭代器生成器(一)
for循环可以用于python中任何序列类型,包括序列.元组以及字符串.例如: >>> for x in [1,2,3,4]: print(x * 2,end='')...2468 ...
- 不错的 HttpHelper类 c#
/// <summary>/// 类说明:HttpHelper类,用来实现Http访问,Post或者Get方式的,直接访问,带Cookie的,带证书的等方式,可以设置代理/// 重要提示: ...
- powerdesinger(MSSQLSRV2008测试通过)通过Name或comment 导出注释到sql脚本,生成sql的说明备注,包括表注释信息
导出字段信息name注释到sql2008字段的说明 在database -> edit current dbms -> MSSQLSRV2008::Script\Objects\Colum ...
- JanaScript数据类型
数据类型 一.基础类型值包括:undefined.null.boolean.string.number 基础类型分别在内存中占有大小空间,它们的值保存在栈空间,我们通过按值来访问. undefined ...