Вложенная @Transactional при загрузке Spring, вторая транзакция не отменена REQUIRES_NEW - PullRequest
0 голосов
/ 21 февраля 2020
@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 голосов
/ 21 февраля 2020

Как упомянуто здесь: Spring проксифицирует ваш метод с транзакцией внутри того же класса, поэтому вызов вложенного метода того же класса не будет go через перехватчик, но напрямую через ваш собственный экземпляр, что приведет к потере всех поддержка транзакций.

Чтобы избежать этого, вы можете go с помощью собственного прокси-сервера с двумя шагами:

ШАГ 1: создать прокси вашей текущей службы и внедрить его как и любой другой bean-компонент STEP 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());
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...