事务嵌套异常-Transaction rolled back because it has been marked as rollback-only

事务嵌套异常-Transaction rolled back because it has been marked as rollback-only

1.问题出现场景

新增系统角色需要审计通过之后才能执行具体逻辑,审计方法上面有事务,然后对应新增逻辑也有对应事务,因为新增失败时需要更新审计状态,以及记录审计日志,所以对新增逻辑进行了try-catch捕捉,然后新增逻辑报错导致出现这个异常。

2.代码例子

新增代码接口

@Override
@Transactional(rollbackFor = {Exception.class}, propagation = Propagation.REQUIRED)
public Role addRole(NexusRequest<AddRoleFrom> nexusRequest) {
    UserDetailVO me = jwtTokenProperties.getCurrentUserDetailVO();
    AddRoleFrom addRoleFrom = nexusRequest.getPayload();
    long count = this.count(new LambdaQueryWrapper<Role>()
            .eq(Role::getMerCode, me.getMerCode())
            .eq(Role::getRoleName, addRoleFrom.getRoleName()));
    if (count>0){
        throw new CrmException("该角色已存在");
    }
    Role role = new Role();
    role.setRoleName(addRoleFrom.getRoleName());
    role.setMerCode(me.getMerCode());
    role.setValidBeginDate(LocalDate.now());
    role.setRemark(addRoleFrom.getDescription());
    role.setSort(addRoleFrom.getSort());
    this.save(role);
	//这里新增其他角色相关表. 涉及业务删除了
    return role;
}

审计代码

@SneakyThrows
@Override
@Transactional(rollbackFor = {Exception.class}, propagation = Propagation.REQUIRED)
public Boolean verify(NexusRequest<AuditVerifyForm> nexusRequest) {
    try {
        AddRoleFrom form = objectMapper.readValue(auditVersion.getReqData(), new TypeReference<AddRoleFrom>() {
        });
        NexusRequest<AddRoleFrom> request = new NexusRequest<>();
        request.setTraceId(nexusRequest.getTraceId());
        request.setTimestamp(nexusRequest.getTimestamp());
        request.setPayload(form);
        //调用新增角色接口
        roleService.addRole(request);
        //更新审计状态
        crmAuditMapper.updateBackStatusById(crmAudit.getId(), VerifyStatusEnum.Normal.getValue());
    } catch (Exception e) {
        log.error("审批失败{},{}", auditType.getTypeCode(), e.getMessage());
        //更新审计失败状态
        crmAuditMapper.updateBackStatusById(crmAudit.getId(), VerifyStatusEnum.Fail.getValue());
        //更新审计日志状态,以及失败原因
        crmAuditLogService.updateAuditLogStatus(auditLog.getId(), VerifyStatusEnum.Fail.getValue(), e.getMessage());
    }
}

3.解决办法

  • 第一种: 删除新增角色接口里面的事务, 但是我们在新增角色表有其他的新增,要保持事务一致性, 肯定不能删除.

  • 第二种: 在审计接口catch使用 throw new CrmException 把异常抛出. 但是我们审计接口最下面还有其他执行逻辑不能抛出

  • 第三种: 更改新增角色接口里面的事务策略, 把propagation = Propagation.REQUIRED 改为propagation = Propagation.REQUIRED_NEW

@Override
@Transactional(rollbackFor = {Exception.class}, propagation = Propagation.REQUIRES_NEW)
public Role addRole(NexusRequest<AddRoleFrom> nexusRequest) {
    UserDetailVO me = jwtTokenProperties.getCurrentUserDetailVO();
    AddRoleFrom addRoleFrom = nexusRequest.getPayload();
    long count = this.count(new LambdaQueryWrapper<Role>()
            .eq(Role::getMerCode, me.getMerCode())
            .eq(Role::getRoleName, addRoleFrom.getRoleName()));
    if (count>0){
        throw new CrmException("该角色已存在");
    }
    Role role = new Role();
    role.setRoleName(addRoleFrom.getRoleName());
    role.setMerCode(me.getMerCode());
    role.setValidBeginDate(LocalDate.now());
    role.setRemark(addRoleFrom.getDescription());
    role.setSort(addRoleFrom.getSort());
    this.save(role);
	//这里新增其他角色相关表. 涉及业务删除了
    return role;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值