@Transactional 不回滚

@Transactional not rolling back

一个 @Transactional 方法调用另外 2 个方法,这些方法也存在于 @Transactional 方法中,但是当其中一个被调用方法出现异常时,事务应该回滚,但它没有发生

-----The Main Transactional method-------------
@Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = RestException.class)
    public BaseDto createFPSAndUser(FpsStoreDto fpsStoreDto){

        log.info("<--Starts FPSStoreService .createFPSAndUser-->"+fpsStoreDto);
        BaseDto baseDto = new BaseDto();
        try {
            UserDetailDto  userDetailDto = fpsStoreDto.getUserDetailDto();
            userDetailDto.setCreatedBy(fpsStoreDto.getCreatedBy());
            baseDto = createFPSStore(fpsStoreDto);
            if(baseDto.getStatusCode() != 0){
                throw new RestException(ErrorCodeDescription.getDescription(baseDto.getStatusCode()));

            }
            userDetailDto.setFpsStore(null);
            baseDto = userDetailService.createUserDetail(userDetailDto);
            if(baseDto.getStatusCode() != 0){
                throw new RestException(ErrorCodeDescription.getDescription(baseDto.getStatusCode()));
            }
            FPSStore fpsStore =  fpsStoreRepository.findByCode(fpsStoreDto.getCode());
            UserDetail userDetail = userDetailRepository.findByUserId(userDetailDto.getUserId());
            userDetail.setFpsStore(fpsStore);
            userDetailRepository.save(userDetail);
            baseDto.setStatusCode(0);
        } catch(RestException restException){
            log.info("RestException -:", restException);
            restException.printStackTrace();
            baseDto.setStatusCode(baseDto.getStatusCode());
        } catch (Exception exception) {
            log.info("Exception -:",exception);
            exception.printStackTrace();
            baseDto.setStatusCode(ErrorCodeDescription.ERROR_GENERIC.getErrorCode());
        }
        log.info("<--Ends FPSStoreService .createFPSAndUser-->"+baseDto);
        return baseDto;
    }

------------------Called method 1st-----------

@Transactional(propagation = Propagation.REQUIRED)
    public BaseDto createFPSStore(FpsStoreDto fpsStoreDto) {
    _________________________
    __________________________
    ________________________
 return baseDto;

}

------------------------2nd Transactional method-----
@Transactional(propagation = Propagation.REQUIRED)
    public BaseDto createUserDetail(UserDetailDto userDetaildto) {
_______________
_______________
_______________
return baseDto
}

您已设置 rollbackFor=RestException.class,但您的代码捕获了那个异常并且没有重新抛出它。从 Spring 的角度来看 RestException 从未被该方法抛出,并且没有理由回滚事务。

如果您希望回滚发生,您需要在 catch 块的末尾执行 throw restException;

您告诉 Spring 只有在

时才回滚事务
rollbackFor = RestException.class

但是如果你捕捉到异常

catch(RestException restException){

Spring 永远不会注意到抛出异常。你需要删除你的捕获块(它们两个)你可以在你的捕获结束时抛出异常

    catch(RestException restException){
        log.info("RestException -:", restException);
        restException.printStackTrace();
        baseDto.setStatusCode(baseDto.getStatusCode());
        throw restException;
    }

@Transactional 告诉容器 (spring) 处理注释方法调用的事务管理。

  • 这是使用代理完成的,参见 understanding aop proxies 这意味着:
    • 注解只被认为是对被注解对象的外部调用
    • 只有在方法边界之外抛出的异常才会由容器处理

`

  • 每个带注释的方法都有其 ,这意味着:
    • 即使你的main方法有参数rollbackFor=RestException.class 内部的不会继承配置,也不会在抛出 rest 异常时触发回滚
    • 如果内部方法在执行过程中抛出异常触发回滚,即使异常被调用者捕获,事务也会回滚,后续每次访问数据库都会导致UnexpectedRollbackException