在春季启动时嵌套@Transactional,第二个事务不能回滚REQUIRES_NEW

时间:2020-02-21 07:10:32

标签: spring spring-boot

@Override
@Transactional(transactionManager="db1PlatformTransactionManager", propagation= Propagation.REQUIRED_NEW, rollbackFor = {InsufficientFundsException.class, EntityNotFoundException.class}, isolation=Isolation.READ_COMMITTED)
public Account creditAmount(AccountDto accountDto, BigDecimal creditAmt) throws EntityNotFoundException{
    throw new EntityNotFoundException(Account.class, "accountNumber", accountDto.getAccountNumber().toString());
}

@Override
@Transactional(transactionManager="db1PlatformTransactionManager", propagation= Propagation.REQUIRED_NEW, rollbackFor = {InsufficientFundsException.class, EntityNotFoundException.class}, isolation=Isolation.READ_COMMITTED)
public Account debitAmount(AccountDto accountDto, BigDecimal debitAmt) throws EntityNotFoundException, InsufficientFundsException {
    assert(debitAmt.compareTo(BigDecimal.ZERO) == 1); //assert greater than 0
    Optional<Account> accountInDb = accountRepository.findById(accountDto.getAccountNumber());
    if (accountInDb.isPresent()) {
        Account account = accountInDb.get();
        account.debit(debitAmt);
        return accountRepository.save(account);
    }
    throw new EntityNotFoundException(Account.class, "accountNumber", accountDto.getAccountNumber().toString());
}



@Override
@Transactional(transactionManager="db1PlatformTransactionManager", propagation=Propagation.REQUIRED, rollbackFor = {InsufficientFundsException.class, EntityNotFoundException.class}, isolation=Isolation.READ_COMMITTED)
public List<Account> transferFunds(AccountDto debitAccountDto, AccountDto creditAccountDto, BigDecimal amount) throws EntityNotFoundException, InsufficientFundsException {
    assert(amount.compareTo(BigDecimal.ZERO) == 1); //assert greater than 0
    Account debitAccount = debitAmount(debitAccountDto, amount);
    Account creditAccount = creditAmount(creditAccountDto, amount); // throws exception 
    return Stream
            .of(debitAccount, creditAccount)
            .collect(Collectors.toList());
}

如您所见,creditAmount方法抛出异常,而debitAmount方法的PRAPOGATION为REQUIRED_NEW。因此除外,因为debitAmount应该提交数据,但它也会回滚

1 个答案:

答案 0 :(得分:0)

如此处所述: Spring使用同一个类中的事务来代理您的方法,因此调用同一个类的嵌套方法将不会通过拦截器,而是直接通过您自己的实例,这会导致您失去所有事务支持。

为避免这种情况,您可以通过两个步骤使用自我代理:

第1步:创建您当前服务的代理并将其注入其他任何bean 第2步:对于内部方法,请使用在第一步中创建的proxyBean。它应该像这样:

  //@Autowired
  //or instancied by your constructror
  private YourCurrentService selfProxified;

  @Override
  @Transactional(transactionManager="db1PlatformTransactionManager", propagation=Propagation.REQUIRED, rollbackFor = {InsufficientFundsException.class, EntityNotFoundException.class}, isolation=Isolation.READ_COMMITTED)
  public List<Account> transferFunds(AccountDto debitAccountDto, AccountDto creditAccountDto, BigDecimal amount) throws EntityNotFoundException, InsufficientFundsException {
    assert(amount.compareTo(BigDecimal.ZERO) == 1); //assert greater than 0
    Account debitAccount = selfProxified.debitAmount(debitAccountDto, amount);
    Account creditAccount = selfProxified.creditAmount(creditAccountDto, amount); // throws exception 
    return Stream
        .of(debitAccount, creditAccount)
        .collect(Collectors.toList());
  }
相关问题