Ответ
Аннотация @Transactional в Spring предоставляет декларативное управление транзакциями на основе AOP (Aspect-Oriented Programming). Она избавляет разработчика от написания шаблонного кода для открытия, коммита и отката транзакций.
Ключевые атрибуты и их поведение:
- propagation (распространение): Определяет, как должна вести себя транзакция при наличии уже существующей.
REQUIRED(по умолчанию): Использует текущую транзакцию или создаёт новую.REQUIRES_NEW: Всегда создаёт новую транзакцию, приостанавливая текущую.NESTED: Создаёт вложенную транзакцию внутри текущей.
- isolation (изоляция): Определяет уровень изоляции транзакции (например,
READ_COMMITTED). - readOnly: Указывает, что транзакция только для чтения (может оптимизировать работу).
- timeout: Время (в секундах), после которого транзакция будет откатана.
- rollbackFor / noRollbackFor: Указывает, для каких исключений выполнять или не выполнять откат.
Пример использования:
@Service
public class TransferService {
@Autowired
private AccountRepository repository;
@Transactional(propagation = Propagation.REQUIRED,
isolation = Isolation.READ_COMMITTED,
rollbackFor = {InsufficientFundsException.class, DataAccessException.class})
public void transferMoney(Long fromId, Long toId, BigDecimal amount) {
Account from = repository.findById(fromId).orElseThrow();
Account to = repository.findById(toId).orElseThrow();
from.debit(amount); // Списание
to.credit(amount); // Зачисление
repository.save(from);
repository.save(to);
// При любом unchecked исключении или указанном в rollbackFor произойдёт автоматический rollback.
}
}
Важные нюансы:
- Проксирование:
@Transactionalработает через динамические прокси (или AspectJ), поэтому вызов метода@Transactionalизнутри того же класса (например, черезthis.internalMethod()) не будет перехвачен прокси, и транзакция не откроется. Нужно использовать инъекцию самого бина или@Transactionalна вызываемом публичном методе. - Тестирование: В интеграционных тестах можно использовать
@Transactionalдля автоматического отката изменений после каждого теста. - Менеджеры транзакций: Для работы требуется правильно настроенный
PlatformTransactionManager(например,DataSourceTransactionManagerдля JDBC).