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

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. BZOJ 3170 [Tjoi2013]松鼠聚会

    题解:切比雪夫距离转化为曼哈顿距离 枚举源点,横纵坐标互不影响,分开考虑,前缀和优化 横纵分开考虑是一种解题思路 #include<iostream> #include<cstdio ...

  2. 图数据库ubentu环境neo4j安装

    1.下载进入官网下载https://neo4j.com/download-center/#releases 2.设置依赖仓库 wget -O - https://debian.neo4j.org/ne ...

  3. UML-架构分析-基础

    1.何时开始架构分析? 最好在第一次迭代前开始.因为,架构分析的失败会导致高风险.如:必须支持英语.在一秒响应时间内支持500个并发事务. UP是迭代和进化的(不是瀑布式的),所以架构分析和开发工作齐 ...

  4. postman批量接口测试注意事项

    1.使用cvs文件 导入文件后最后行出现\r符号 用文本打开 删除最后一行空白行 2.打印cvs文件中的接口调用的参数 Pre-request Script: var beginDate=data.b ...

  5. 4. 现代 javascript class 专题 和 异步专题

    class 专题 定义 class //es5 类的定义  属性定义在 function 上, 方法定义在原型链上 function foobar(){ this.foo_ = 'foo'; this ...

  6. vue多选验证

    vue select 多选 验证 <FormItem :prop="'formList.'+index+'.name'" label="姓名" :rule ...

  7. 系统学习python第五天学习笔记

    1.列表补充 extend() li = ["alex", "WuSir", "ritian", "barry", &q ...

  8. Cracking Digital VLSI Verification Interview 第四章

    目录 Hardware Description Languages Verilog SystemVerilog 对Cracking Digital VLSI Verification Intervie ...

  9. format 可以用 * 星号

    procedure TForm1.FormCreate(Sender: TObject); var s:string; a:integer; b:Single; begin a:=; b:=108.4 ...

  10. Samba 文件共享

    介绍:用于Linux系统与Windows系统之间共享文件资源,小文件可以使用lrzsz,大文件可以使用samba 测试环境: [root@localhost home]# cat /etc/redha ...