Расскажи про использование аннотации @Transactional в Spring.

«Расскажи про использование аннотации @Transactional в Spring.» — вопрос из категории Spring, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Аннотация @Transactional в Spring декларативно управляет транзакциями, избавляя от необходимости писать шаблонный код для их начала, коммита или отката.

Ключевые параметры:

Параметр Описание Пример значения
propagation Поведение транзакции относительно существующей. Propagation.REQUIRED (по умолчанию) — использует текущую или создаёт новую. REQUIRES_NEW — всегда создаёт новую.
isolation Уровень изоляции транзакции. Isolation.READ_COMMITTED (чаще всего) — читаются только закоммиченные данные.
timeout Таймаут транзакции в секундах. 30
readOnly Оптимизация для операций только чтения. true
rollbackFor / noRollbackFor Классы исключений для отката/игнорирования отката. rollbackFor = Exception.class

Пример использования:

@Service
public class TransferService {

    @Autowired
    private AccountRepository accountRepository;

    @Transactional(
        propagation = Propagation.REQUIRED,
        isolation = Isolation.READ_COMMITTED,
        timeout = 30,
        rollbackFor = {InsufficientFundsException.class, DataAccessException.class}
    )
    public void transferMoney(Long fromId, Long toId, BigDecimal amount) {
        Account from = accountRepository.findById(fromId).orElseThrow();
        Account to = accountRepository.findById(toId).orElseThrow();

        from.debit(amount); // Списание
        to.credit(amount);  // Зачисление

        accountRepository.save(from);
        accountRepository.save(to);
        // При любом исключении из указанных в rollbackFor произойдёт откат обоих save
    }
}

Важные ограничения:

  • Работает только на public-методах.
  • Самовызов внутри класса (вызов одного @Transactional-метода из другого метода того же класса) не работает из-за ограничений AOP-проксирования. Для этого нужно использовать self-injection или AspectJ mode.
  • По умолчанию откат происходит только для RuntimeException и Error.