我们在实现业务逻辑时,经常会有这种需求:

1、在当前事务A中开启新事务B,事务B中发生异常不可以回滚A,事务B成功执行后返回事务B的返回值;

2、在当前事务A中开启新事务B,事务B中发生异常要求回滚A,事务B成功执行后返回事务B的返回值;

3、在当前事务A中开启新事务B,事务B中发生异常不可以回滚A,事务B成功执行后不需要返回;

4、在当前事务A中开启新事务B,事务B中发生异常要求回滚A,事务B成功执行后不需要返回;

5、注册后置事务B,即当前事务A成功提交后才会执行事务B,事务B异常的话不抛出,只打印异常日志;

6、注册后置事务B,即当前事务A异常时执行事务B,事务B异常的话不抛出,只打印异常日志;

一、配置事务模版

<!--事务模版
1.标志REQUIRES_NEW会新开启事务,外层事务异常外部事务会会馆,不会回滚内部事务的提交
2.标志REQUIRES_NEW的内部事务的异常,内部事务会回滚,外部事务也会回滚-->
<bean id="transactionTemplateNew" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="propagationBehaviorName" value="PROPAGATION_REQUIRES_NEW"/>
</bean>

二、定义接口

/**
* @author zhaojiatao
* @date 2019-07-14
*/
public interface ICommonTransactionService { /**
* 开启一个新事务来执行函数,有返回值;与外部事务互相隔离,发生异常只回滚本事务,不会互相影响
* @param action
* @param <T>
* @urn
*/
<T> T newTransactionExecuteAndReturnWithOutThrowable(Supplier<T> action); /**
* 开启一个新事务来执行函数,有返回值;内部事务发生异常时会向外抛出异常,内部事务和外部事务均回滚
* @param action
* @param <T>
* @urn
*/
<T> T newTransactionExecuteAndReturnThrowable(Supplier<T> action) throws Exception; /**
* 开启一个新事务来执行函数,无返回值;与外部事务互相隔离,发生异常只回滚本事务,不会互相影响
* @param f
*/
void newTransactionRunVoidWithOutThrowable(Runnable f); /**
* 开启一个新事务来执行函数,无返回值;内部事务发生异常时会向外抛出异常,内部事务和外部事务均回滚
* @param f
*/
void newTransactionRunVoidThrowable(Runnable f) throws Exception; /**
* 如果当前存在事务,则等当前事务提交后,回头来开启一个新事务执行,如果内部捕捉异常,不往外抛出;如果外部事务提交前外部事物异常,则此函数不会被执行
* https://docs.spring.io/spring/docs/1.2.7/javadoc-api/org/springframework/transaction/support/TransactionSynchronizationAdapter.html
* @param f
*/
void registerTransactionAfterCommitNoThrowable(Runnable f); /**
* 当前事务提交或者回滚后执行 Invoked after transaction commit/rollback
* https://docs.spring.io/spring/docs/1.2.7/javadoc-api/org/springframework/transaction/support/TransactionSynchronizationAdapter.html
* @param f
*/
void registerTransactionAfterRollBackNoThrowable(Runnable f); }

三、接口实现

/**
* @author zhaojiatao
* @date 2019-07-14
*/ @Slf4j
@Service("commonTransactionService")
public class CommonTransactionServiceImpl implements ICommonTransactionService { @Autowired
@Qualifier("transactionTemplateNew")
TransactionTemplate transactionTemplateNew; @Override
public <T> T newTransactionExecuteAndReturnWithOutThrowable(Supplier<T> action) {
//执行带有返回值<Object>的事务管理
return transactionTemplateNew.execute(transactionStatus-> {
try {
return action.get();
} catch (Exception e) {
log.error("newTransactionExecuteAndReturnNoThrowable发生异常",e);
//回滚
transactionStatus.setRollbackOnly();
return null;
}
});
} @Override
public <T> T newTransactionExecuteAndReturnThrowable(Supplier<T> action) {
//执行带有返回值<Object>的事务管理
return transactionTemplateNew.execute(transactionStatus-> {
try {
return action.get();
} catch (Exception e) {
log.error("newTransactionExecuteAndReturnNoThrowable发生异常",e);
//回滚
transactionStatus.setRollbackOnly();
throw e;
}
});
} @Override
public void newTransactionRunVoidWithOutThrowable(Runnable f) {
//执行无返回值的事务管理
transactionTemplateNew.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
try {
//业务代码
f.run();
} catch (Exception e){
log.error("newTransactionRunVoidNoThrowable发生异常",e);
//回滚
transactionStatus.setRollbackOnly();
} }
}); } @Override
public void newTransactionRunVoidThrowable(Runnable f) {
//执行无返回值的事务管理
transactionTemplateNew.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
try {
//业务代码
f.run();
} catch (Exception e){
log.error("newTransactionRunVoidNoThrowable发生异常",e);
//回滚
transactionStatus.setRollbackOnly();
throw e;
} }
}); } @Override
public void registerTransactionAfterCommitNoThrowable(Runnable f) {
try{
if (TransactionSynchronizationManager.isActualTransactionActive()) {
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
f.run();
}
});
} else {
f.run();
}
}catch (Exception e){
log.error("执行后置事务发生异常",e);
} } @Override
public void registerTransactionAfterRollBackNoThrowable(Runnable f) {
try{
if (TransactionSynchronizationManager.isActualTransactionActive()) {
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void afterCompletion(int status) {
log.error("执行事务回滚后置事务,status={}",status);
f.run();
}
});
} else {
f.run();
}
}catch (Exception e){
log.error("当前事务回滚后置事务发生异常",e);
}
} }

四、调用

@Test
@Transactional(rollbackFor = Exception.class)
public void commonTransactionServiceTest() throws Exception { //1、newTransactionExecute 开启新事务 有返回值
String result=commonTransactionService.newTransactionExecuteAndReturnWithOutThrowable(
()->{
QueryObj queryObj = new QueryObj();
queryObj.setQuerydo(new OrderDO());
queryObj.addQueryParam(new QueryParam("id = #{id}", "347"));
OrderDO orderDO = orderDAO.querySingle(queryObj);
return JSON.toJSONString(orderDO);
}
); log.info(result); //2、newTransactionRun 开启新事务 无返回值
commonTransactionService.newTransactionRunVoidWithOutThrowable(
()->{
QueryObj queryObj = new QueryObj();
queryObj.setQuerydo(new OrderDO());
queryObj.addQueryParam(new QueryParam("id = #{id}", "347"));
OrderDO orderDO = orderDAO.querySingle(queryObj);
log.info(JSON.toJSONString(orderDO));
}
); int[] ids=new int[]{0}; //3、在新事务中insert数据
commonTransactionService.newTransactionRunVoidWithOutThrowable(
()->{
OrderDO orderDO=new OrderDO();
orderDO.setId(350L);
orderDO.setOrderCode("350350");
orderDO.setCustomerId(81L);
orderDO.setBusinessModel(LoanOrderBusinessModelEnum.SELF_SECOND_CAR_ICBC_DIRECT.getCode());
ids[0]=orderDAO.create(orderDO);
log.info( ids[0]+"");
//只回滚内部事务,不回滚外部事务
System.out.println(1/0);
}
); //4、在外部事务提交后执行的后置新事务insert数据
commonTransactionService.registerTransactionAfterCommitNoThrowable(
()->{
OrderDO orderDO=new OrderDO();
orderDO.setId(351L);
orderDO.setOrderCode("351351");
orderDO.setCustomerId(81L);
orderDO.setBusinessModel(LoanOrderBusinessModelEnum.SELF_SECOND_CAR_ICBC_DIRECT.getCode());
ids[0]=orderDAO.create(orderDO);
log.info( ids[0]+"");
} ); //5、在外部事务中insert数据
if(true){
OrderDO orderDO=new OrderDO();
orderDO.setId(352L);
orderDO.setOrderCode("352352");
orderDO.setCustomerId(81L);
orderDO.setBusinessModel(LoanOrderBusinessModelEnum.SELF_SECOND_CAR_ICBC_DIRECT.getCode());
ids[0]=orderDAO.create(orderDO);
log.info( ids[0]+"");
} //6、在新事务中插入数据并异常
commonTransactionService.newTransactionRunVoidThrowable(
()->{
OrderDO orderDO=new OrderDO();
orderDO.setId(353L);
orderDO.setOrderCode("353353");
orderDO.setCustomerId(81L);
orderDO.setBusinessModel(LoanOrderBusinessModelEnum.SELF_SECOND_CAR_ICBC_DIRECT.getCode());
ids[0]=orderDAO.create(orderDO);
log.info( ids[0]+"");
System.out.println(1/0);
}
); //注意验证这个异常是无法回滚commonTransactionService.newTransactionRun的
//注意验证这个异常会导致commonTransactionService.registerTransactionAfterCommitNoThrowable无法执行,因为事务没有提交
// System.out.println(1/0);
System.out.println(1); }

使用lambda表达式优雅你的事务代码的更多相关文章

  1. Lambda表达式, 可以让我们的代码更优雅.

    在C#中, 适当地使用Lambda表达式, 可以让我们的代码更优雅. 通过lambda表达式, 我们可以很方便地创建一个delegate: 下面两个语句是等价的 Code highlighting p ...

  2. Java 8 Lambda表达式,让你的代码更简洁

    Lambda表达式是Java 8一个非常重要的新特性.它像方法一样,利用很简单的语法来定义参数列表和方法体.目前Lambda表达式已经成为高级编程语言的标配,像Python,Swift等都已经支持La ...

  3. golang如何优雅的编写事务代码

    目录 前言 需求 烂代码示例 重构套路 一.提前返回去除if嵌套 二.goto+label提取重复代码 三.封装try-catch统一捕获panic 前言 新手程序员概有如下特点 if嵌套特别多.重复 ...

  4. 委托学习笔记后续:泛型委托及委托中所涉及到匿名方法、Lambda表达式

    引言: 最初学习c#时,感觉委托.事件这块很难,其中在学习的过程中还写了一篇学习笔记:委托.事件学习笔记.今天重新温故委托.事件,并且把最近学习到和委托相关的匿名方法.Lambda表达式及泛型委托记录 ...

  5. Lambda表达式的前世今生

    Lambda 表达式 早在 C# 1.0 时,C#中就引入了委托(delegate)类型的概念.通过使用这个类型,我们可以将函数作为参数进行传递.在某种意义上,委托可理解为一种托管的强类型的函数指针. ...

  6. 掌握 Java 8 Lambda 表达式

    Lambda 表达式 是 Java8 中最重要的功能之一.使用 Lambda 表达式 可以替代只有一个函数的接口实现,告别匿名内部类,代码看起来更简洁易懂.Lambda 表达式 同时还提升了对 集合 ...

  7. 泛型委托及委托中所涉及到匿名方法、Lambda表达式

    泛型委托及委托中所涉及到匿名方法.Lambda表达式 引言: 最初学习c#时,感觉委托.事件这块很难,其中在学习的过程中还写了一篇学习笔记:委托.事件学习笔记.今天重新温故委托.事件,并且把最近学习到 ...

  8. C++雾中风景8:Lambda表达式

    上一篇C++的博客是Long Long ago了,前文讲到在看Lambda表达式的内容.笔者首次接触Lambda表达式应该是学习Python语言的时候,当时也不太明白这种表达方式的精髓,后续接触了Sc ...

  9. 【原创】从策略模式闲扯到lambda表达式

    引言 策略模式,讲这个模式的文章很多,但都缺乏一个循序渐进的过程.讲lambda表达式的文章也很多,但基本都是堆砌一堆的概念,很少带有自己的见解.博主一时兴起,想写一篇这二者的文章.需要说明的是,在看 ...

随机推荐

  1. 从1到n整数中1的个数

    [问题]求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1.10.11.12.13因此共出现6次,但是对于后面问题他就没辙了.A ...

  2. zabbix监控tcp/nginx/memcache连接数自定义监控shell

    #!/bin/bashtcp_status_fun(){ TCP_STAT=$1 #netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in st ...

  3. nginx log 切割

    /logs/nginx/*/*access.log { daily rotate 30 missingok dateext #compress notifempty sharedscripts pos ...

  4. 12 react 基础 的 css 过渡动画 及 动画效果 及 使用 react-transition-group 实现动画

    一. 过渡动画 # index.js import React from 'react';import ReactDOM from 'react-dom';import App from './app ...

  5. Windb实践之Script Command

    1.输出参数 .echo The first argument is ${$arg1}. .echo The fifth argument is ${$arg5}. .echo The fourth ...

  6. HDU 1298 T9 字典树+DFS

    必须要批评下自己了,首先就是这个题目的迟疑不定,去年做字典树的时候就碰到这个题目了,当时没什么好的想法,就暂时搁置了,其实想法应该有很多,只是居然没想到. 同样都是对单词进行建树,并插入可能值,但是拨 ...

  7. (转)绝对路径${pageContext.request.contextPath}用法及其与web.xml中Servlet的url-pattern匹配过程

    以系统的一个“添加商品”的功能为例加以说明,系统页面为add.jsp,如图一所示: 图一  添加商品界面 系统的代码目录结构及add.jsp代码如图二所示: 图二   系统的代码目录结构及add.js ...

  8. vSphere 6.7 新特性 — 基于虚拟化的安全 (VBS)

    https://blogs.vmware.com/china/2018/07/27/vsphere-6-7-%E6%96%B0%E7%89%B9%E6%80%A7-%E5%9F%BA%E4%BA%8E ...

  9. 第22章 Makefile基础

    一.自动处理头文件的依赖关系 在Makefile中插入如下代码: include $(sources:.c=.d) %.d: %.c set -e; rm -f $@; \ $(CC) -MM $(C ...

  10. echarts图表重设尺寸

    在绘制chart的方法中添加下面语句,则会在尺寸变化的时候,重新绘制图表 window.addEventListener("resize", function () { myCha ...