0
点赞
收藏
分享

微信扫一扫

代码验证REQUIRES_NEW事务传播机制


源码注释

源码说,创建一个新事务,如果已存在一个事务,会将上层的事务挂起(暂停),意思就是你玩你的,我玩我的。

/**
* Create a new transaction, suspending the current transaction if one exists.
* Analogous to the EJB transaction attribute of the same name.
* <p><b>NOTE:</b> Actual transaction suspension will not work out-of-the-box
* on all transaction managers. This in particular applies to
* {@link org.springframework.transaction.jta.JtaTransactionManager},
* which requires the {@code jakarta.transaction.TransactionManager} to be
* made available it to it (which is server-specific in standard Jakarta EE).
* <p>A {@code PROPAGATION_REQUIRES_NEW} scope always defines its own
* transaction synchronizations. Existing synchronizations will be suspended
* and resumed appropriately.
* @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
*/
int PROPAGATION_REQUIRES_NEW = 3;

测试环境

jdk17+mysql8+spring5.2

controller

定义一个controller,就为了方便调用service

@RestController
@RequestMapping("/api/test")
@Api(value = "测试", tags = "测试")
class StudentController extends ZubusBaseApi {
@Autowired
MutService mutService;

@RequestMapping(value = "/add", method = RequestMethod.PUT)
public ApiResult testUpdateUser(@RequestBody SysUser user) {
user = new SysUser();
user.setUserID(1L);
user.setUserName("懒羊羊");


Integer updateUserName = mutService.testUpdateUser(user);


return new ApiResult().success(updateUserName);
}

}

定义一个mutService

为了聚合两个不同service,很多人为了省事,在同一个service里面测试,很容易因为自调用导致事务失效而影响测试结果,详情请参考@Transactional 事务失效场景分析

@Service
public class MutService {

@Autowired
SysUserService sysUserService;

@Autowired
SysUserService2 sysUserService2;


@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public Integer testUpdateUser(SysUser user) {

Integer res = sysUserService.updateUser(user);// 熊大 改为懒羊羊

Integer delUserById = sysUserService2.delUserById(97L);// 熊二 改为喜羊羊 抛异常

// 模拟异常
//int a = 1/0;

return res + delUserById;
}

}

SysUserService 

@Service
public class SysUserService {

@Autowired
private SysUserMapper mapper;

@Transactional(propagation = Propagation.REQUIRES_NEW)
public Integer updateUser(SysUser user) {
return mapper.updateUser(user);
}

SysUserService2 

@Service
public class SysUserService2 {

@Autowired
private SysUserMapper mapper;

/**
* 内层方法
* @param userID
* @return
*/
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)
public Integer delUserById(Long userID) {

SysUser user = new SysUser();
user.setUserID(userID);
user.setUserName("喜羊羊");

Integer deleteById = mapper.updateById(user);

// 模拟异常
//int a = 1/0;

return deleteById;
}

}

数据准备

在数据库准备两天数据,一条名字叫熊大,一条名字叫熊二

代码验证REQUIRES_NEW事务传播机制_spring传播特性

 测试

外无内有,内异常

即mutService不加  Transactional 注解,而 sysUserService和sysUserService2均有注解,传播特性均为 REQUIRES_NEW,且在sysUserService2里面模拟一个异常

代码验证REQUIRES_NEW事务传播机制_spring传播特性_02

 

代码验证REQUIRES_NEW事务传播机制_spring传播特性_03

 

代码验证REQUIRES_NEW事务传播机制_数据_04

 测试结果报错,/ by zero

代码验证REQUIRES_NEW事务传播机制_spring事务_05

 

查看数据库数据

熊大被改成了懒羊羊,而熊二没有,说明在外部没有事务的情况下,内部事务的异常不会影响外部。

代码验证REQUIRES_NEW事务传播机制_spring事务_06

内外皆有,内异常

将数据恢复原样,把mutService的事务注解开启,其余和上面一样

代码验证REQUIRES_NEW事务传播机制_REQUIRES_NEW_07

代码验证REQUIRES_NEW事务传播机制_spring_08

 

测试结果,依旧报异常

代码验证REQUIRES_NEW事务传播机制_REQUIRES_NEW_09

 

查看数据库数据

依旧是熊大被改成了懒羊羊,而熊二没有,说明在外部有事务的情况下,内部事务的异常也不会影响外部。

代码验证REQUIRES_NEW事务传播机制_spring_10

 

 

内外皆有,外异常

内外均开启 Transactional 注解 ,把内部异常注释,在外部模拟一个异常

代码验证REQUIRES_NEW事务传播机制_spring_11

 

代码验证REQUIRES_NEW事务传播机制_spring传播特性_12

 与预期一致,报了异常

代码验证REQUIRES_NEW事务传播机制_数据_13

 

查看数据库数据

两个数据都正常提交了,说明在 REQUIRES_NEW 传播行为下,内外事务是独立的,互不干扰。

代码验证REQUIRES_NEW事务传播机制_spring事务_14

 

举报

相关推荐

0 条评论