SpringBoot中异步执行事务REQUIRED和REQUIRED_NEW的区别
springboot中事务的使用方式
在spring的bean中,要开启数据库事务只需要在方法中标注注解
@Transactional
注解常用的参数有
- Class[] rollbackFor() default {} 指定回滚异常
- Propagation propagation() default Propagation.REQUIRED 事务的传播机制
- Isolation isolation() default Isolation.DEFAULT 事务的隔离级别
事务传播机制REQUIRED和REQUIRED_NEW
REQUIRED是默认的级别,如果当前没有事务,创建新事务;如果有事务,加入当前事务
REQUIRED_NEW 如果无论当前有没有事务,开启一个新的事务
Spring异步注解@Async
启动类中加入注解@EnableAsync
@Async注解标注在方法中,使方法异步执行
测试
通过调用接口新增数据
test1方法中保存了code为-1的一条数据
test2方法中保存了code为0~9的十条数据,插入第四条数据会抛出异常报错
@Resource
private TestBaseService testBaseService;
@Resource
private ApplicationContext applicationContext;
@GetMapping("/add")
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
public void test1() {
TestBaseEntity preEntity = new TestBaseEntity();
preEntity.setCode("-1");
testBaseService.save(preEntity);
TestBaseController bean = applicationContext.getBean(TestBaseController.class);
for (int i = 0; i < 10; i++) {
TestBaseEntity entity = new TestBaseEntity();
entity.setCode(String.valueOf(i));
bean.test2(entity, i);
}
}
//@Async
//@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public void test2(TestBaseEntity entity, int i) {
testBaseService.save(entity);
if (i == 4) {
throw new RuntimeException("异常");
}
}
调用接口,发现没有数据新增
因为只设置了一个事务,有异常会导致事务回滚;有一条失败全部失败
test1设置事务提交后,再执行test2
@GetMapping("/add")
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
public void testTransactional() {
TestBaseEntity preEntity = new TestBaseEntity();
preEntity.setCode("-1");
testBaseService.save(preEntity);
TestBaseController bean = applicationContext.getBean(TestBaseController.class);
for (int i = 0; i < 10; i++) {
TestBaseEntity entity = new TestBaseEntity();
entity.setCode(String.valueOf(i));
int finalI = i;
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@Override
public void afterCommit() {
bean.saveTest(entity, finalI);
TransactionSynchronization.super.afterCommit();
}
});
}
}
结果图
可以看到 -1 ~ 4都新增成功了
因为手动将test1的事务提交了,而test2没有事务,所有即便报错也没有回滚,code=4正常插入
test2传播机制设置为REQUIRED_NEW
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public void test2(TestBaseEntity entity, int i) {
testBaseService.save(entity);
if (i == 4) {
throw new RuntimeException("异常");
}
}
调用接口,结果如下
test1的事务不会因为test2的报错而受到影响,执行的10次test2每次都是一个新的事务
当code=4时,发生异常,当前事务回滚,程序返回,所以code=4的数据回滚了,后面的5-9根本没有执行新增插入
test2传播机制设置为REQUIRED_NEW,开启@Async注解
@Async
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public void test2(TestBaseEntity entity, int i) {
testBaseService.save(entity);
if (i == 4) {
throw new RuntimeException("异常");
}
}
调用接口,结果如下
可以看到除了code=4其他的都新增成功了
因为在每个test2方法新开启了事务,而且方法是异步的,报错异常对本方法以外没有任何影响
原文地址:https://blog.csdn.net/HHCS231/article/details/137996740
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!