使用lambda表达式优雅你的事务代码
我们在实现业务逻辑时,经常会有这种需求:
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表达式优雅你的事务代码的更多相关文章
- Lambda表达式, 可以让我们的代码更优雅.
在C#中, 适当地使用Lambda表达式, 可以让我们的代码更优雅. 通过lambda表达式, 我们可以很方便地创建一个delegate: 下面两个语句是等价的 Code highlighting p ...
- Java 8 Lambda表达式,让你的代码更简洁
Lambda表达式是Java 8一个非常重要的新特性.它像方法一样,利用很简单的语法来定义参数列表和方法体.目前Lambda表达式已经成为高级编程语言的标配,像Python,Swift等都已经支持La ...
- golang如何优雅的编写事务代码
目录 前言 需求 烂代码示例 重构套路 一.提前返回去除if嵌套 二.goto+label提取重复代码 三.封装try-catch统一捕获panic 前言 新手程序员概有如下特点 if嵌套特别多.重复 ...
- 委托学习笔记后续:泛型委托及委托中所涉及到匿名方法、Lambda表达式
引言: 最初学习c#时,感觉委托.事件这块很难,其中在学习的过程中还写了一篇学习笔记:委托.事件学习笔记.今天重新温故委托.事件,并且把最近学习到和委托相关的匿名方法.Lambda表达式及泛型委托记录 ...
- Lambda表达式的前世今生
Lambda 表达式 早在 C# 1.0 时,C#中就引入了委托(delegate)类型的概念.通过使用这个类型,我们可以将函数作为参数进行传递.在某种意义上,委托可理解为一种托管的强类型的函数指针. ...
- 掌握 Java 8 Lambda 表达式
Lambda 表达式 是 Java8 中最重要的功能之一.使用 Lambda 表达式 可以替代只有一个函数的接口实现,告别匿名内部类,代码看起来更简洁易懂.Lambda 表达式 同时还提升了对 集合 ...
- 泛型委托及委托中所涉及到匿名方法、Lambda表达式
泛型委托及委托中所涉及到匿名方法.Lambda表达式 引言: 最初学习c#时,感觉委托.事件这块很难,其中在学习的过程中还写了一篇学习笔记:委托.事件学习笔记.今天重新温故委托.事件,并且把最近学习到 ...
- C++雾中风景8:Lambda表达式
上一篇C++的博客是Long Long ago了,前文讲到在看Lambda表达式的内容.笔者首次接触Lambda表达式应该是学习Python语言的时候,当时也不太明白这种表达方式的精髓,后续接触了Sc ...
- 【原创】从策略模式闲扯到lambda表达式
引言 策略模式,讲这个模式的文章很多,但都缺乏一个循序渐进的过程.讲lambda表达式的文章也很多,但基本都是堆砌一堆的概念,很少带有自己的见解.博主一时兴起,想写一篇这二者的文章.需要说明的是,在看 ...
随机推荐
- HTTP协议(二):作用
前言 上一节我们简单介绍了一下TCP/IP协议族的基本情况,知道了四大层的职责,也了解到我们这一族的家族成员以及他们的能力. 无良作者把我这个主角变成了配角,让我很不爽,好在我打了作者一顿,没错,这次 ...
- 应用架构的演进--MVC,RPC,SOA,微服务架构
MVC架构:垂直应用架构 当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率. 当业务规模很小时,将所有功能都部署在同一个进程中,通过双机或者前置负载均衡 ...
- 解压版mysql安装步骤
第一步:解压mysql,例如解压后的目录在C:\Program Files\mysql-5.6.36-winx64 第二步:配置mysql环境变量,类似配置java的环境变量 计算机右键===> ...
- PyGame快速入门
pygame 快速入门 目标 项目准备 使用 pygame 创建图形窗口 理解 图像 并实现图像绘制 理解 游戏循环 和 游戏时钟 理解 精灵 和 精灵组 项目准备 新建 飞机大战 项目 新建一个 h ...
- SQL基础教程(第2版)第5章 复杂查询:5-1 视图和表
本章将以此前学过的SELECT语句,以及嵌套在SELECT语句中的视图和子查询等技术为中心进行学习.由于视图和子查询可以像表一样进行使用,因此如果能恰当地使用这些技术,就可以写出更加灵活的 SQL 了 ...
- Python不区别字符串大小写的列表比较法
一开始想这样写,结果报了索引错误 后来改正: if user_name.lower() in [names.lower() for names in names]: 我觉得应该是in后面应该跟列表,而 ...
- sudo: /etc/sudoers is mode 0777, should be 0440 单用户 sudo不用输入密码的方法
sudo权限问题考察一题 su - sudo su - sudo su - test [root@localhost ~]# su - zzx #root用户进行切换不需要输入密码 [ ...
- SeetaFaceEngine系列2:Face Alignment编译和使用
前面一篇写了编译人脸检测部分,现在就介绍下人脸配准部分,SeetaFace的Face Alignment通过人脸的五个关键点来配准人脸,也就是双眼.鼻尖.两个嘴角. 这部分的编译也和上一篇一样,步骤如 ...
- 通过gitlab的webhook触发Jenkins自动构建设置
1.Jenkins job中勾选Build when a change is pushed to GitLab 2.Gitlab project 页面setting选择Integrations,配置w ...
- mysql my.ini 性能调优
MYSQL服务器my.cnf配置文档详解 硬件:内存16G [client] port = 3306 socket = /data/3306/mysql.sock [mysql] no-auto-re ...