Ответ
Аннотация @Transactional декларативно управляет транзакциями, гарантируя, что аннотированный метод или класс будет выполняться в контексте транзакции, обеспечивая свойства ACID.
Основные гарантии и поведение:
- Атомарность (Atomicity): Все операции внутри метода выполняются как единое целое. В случае успеха происходит commit, при любом непроверяемом (
RuntimeException) или ошибке (Error) — полный rollback. - Согласованность (Consistency): Транзакция переводит данные из одного валидного состояния в другое.
- Изоляция (Isolation): По умолчанию используется уровень изоляции БД, но его можно настроить (
@Transactional(isolation = Isolation.READ_COMMITTED)). - Долговечность (Durability): Зафиксированные изменения сохраняются.
Практический пример:
@Service
public class TransferService {
@Transactional // Гарантирует атомарность всего метода
public void transferMoney(Long fromId, Long toId, BigDecimal amount) {
Account from = accountRepository.findById(fromId).orElseThrow();
Account to = accountRepository.findById(toId).orElseThrow();
from.debit(amount); // UPDATE account SET balance = balance - ? ...
to.credit(amount); // UPDATE account SET balance = balance + ? ...
// Если здесь выбросится исключение, оба UPDATE откатятся.
}
}
Ключевые настраиваемые атрибуты:
propagation: Поведение при наличии существующей транзакции (например,Propagation.REQUIRED— используется текущая или создается новая).rollbackFor/noRollbackFor: Уточнение, для каких исключений делать откат.readOnly: Подсказка для оптимизации (например,trueдля операций только чтения).
Важно: @Transactional работает через AOP-прокси, поэтому вызовы внутри одного класса (через this.) не будут перехвачены прокси. Также необходима корректная настройка менеджера транзакций.