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

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. 遍历数组提取List[Int]

    def toFlatMap(input:List[Any],result:List[Int]):List[Int]=input match{ case h::t=>h match {case e ...

  2. 纯CSS导航栏下划线跟随效果

    参考文章 <ul> <li>111</li> <li>2222</li> <li>3333333</li> < ...

  3. libcurl在windows下的使用

    curl在linux下很好用,但到了windows下写程序却没办法使用了,这时候可以使用libcurl库 libcurl库的编译网上很多,我就不一一赘述了,curl的官方网站:https://curl ...

  4. openv uMat和Mat数据格式的转换

    Mat 转成 UMat: UMat umat; mat.copyTo(umat); UMat转成 Mat : Mat mat; umat.copyTo(mat);

  5. 刷题33. Search in Rotated Sorted Array

    一.题目说明 这个题目是33. Search in Rotated Sorted Array,说的是在一个"扭转"的有序列表中,查找一个元素,时间复杂度O(logn). 二.我的解 ...

  6. JavaScript 之 DOM 与 BOM

    DOM是文档对象模型,用来获取或设置文档中标签的属性,例如获取或者设置input表单的value值. 由于DOM的操作对象是文档(Document),所以dom和浏览器没有直接关系. BOM是浏览器对 ...

  7. 一线大厂的分布式唯一ID生成方案是什么样的?

    本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...

  8. 201412-1 门禁系统 Java

    类似于201312-1 出现次数最多的数,了解一下Map的containsKey方法和containsValue方法 **containsKey** boolean containsKey(Objec ...

  9. 17.3.12----OS模块ya

    1---他是一xu个python系统编程的操作模块,可以处理文件和目录这些我们日常手动需要做的操作. import os#导入这个os模块,其实python模块就是C元的包含很多函数的文件 2---o ...

  10. macbook 一些php相关操作

    开启php: https://jingyan.baidu.com/article/67508eb434539f9cca1ce4da.html 配置多虚拟主机:  https://jingyan.bai ...