Ответ
Аннотация @Transactional декларативно управляет транзакциями, обеспечивая целостность и согласованность данных в приложениях, работающих с БД. Она защищает от следующих проблем:
- Нарушение атомарности (Atomicity): Гарантирует, что группа операций выполнится как единое целое. При ошибке все изменения откатываются.
- Нарушение согласованности (Consistency): Обеспечивает переход базы данных из одного валидного состояния в другое.
- Проблемы изоляции (Isolation): Управляет видимостью изменений между параллельными транзакциями, предотвращая:
- Грязное чтение (чтение незафиксированных данных).
- Неповторяемое чтение (изменение строки другой транзакцией между двумя чтениями).
- Фантомное чтение (появление новых строк между двумя чтениями).
Практический пример:
@Service
public class TransferService {
@Transactional // Если credit() выбросит исключение, debit() будет откачен
public void transfer(Account from, Account to, BigDecimal amount) {
from.debit(amount); // Списание
to.credit(amount); // Зачисление
}
}
Ключевые атрибуты для настройки защиты:
propagation: Поведение при наличии/отсутствии текущей транзакции (например,REQUIRED,REQUIRES_NEW).isolation: Уровень изоляции (например,READ_COMMITTED,SERIALIZABLE).rollbackFor/noRollbackFor: Какие исключения вызывают откат.readOnly: Оптимизация для операций только на чтение.
Важное ограничение: @Transactional работает через Spring AOP (прокси), поэтому вызов метода @Transactional из другого метода того же класса не будет перехвачен прокси, и управление транзакциями не сработает.