New We are sorting MAX channels into categories and territories. Read the news

Spring: граница транзакции должна охватывать бизнес-операцию целиком.



Например, перевод денег – это списание с одного счёта и зачисление на другой. Разместите оба действия в методе сервиса:
@Service
@RequiredArgsConstructor
public class TransferService {
    private final AccountRepository accounts;

    @Transactional
    public void transfer(Long fromId, Long toId,
                         BigDecimal amount) {
        var from = accounts.findById(fromId).orElseThrow();
        var to = accounts.findById(toId).orElseThrow();

        from.withdraw(amount);
        to.deposit(amount);
    }
}
Оба изменения фиксируются вместе. Если при зачислении возникнет исключение, вызывающее откат, списание тоже отменится.

Контроллеру остаётся проверить входные данные и вызвать сервис. Бизнес-правила находятся рядом с операцией, которую защищает транзакция.

Два нюанса:

- По умолчанию Spring откатывает транзакцию при `RuntimeException` и `Error`. Для checked exceptions можно настроить rollbackFor.
- В стандартном proxy-режиме вызов метода через `this` не активирует `@Transactional`.

Транзакция также не заменяет защиту от конкурентных изменений: для денежных операций отдельно продумайте блокировки или контроль версий.
Views: 100
Open in MAX Report an inaccuracy

Report an inaccuracy

Describe what needs fixing. If you have a source, add a link.

You are leaving datool.ru

The link leads to an external website. datool.ru is not responsible for its content — check the address before entering passwords or payment details.

Redirecting in 10 s

Go