Короткий ответ
@Transactional — аннотация декларативного управления транзакциями: все операции с базой данных внутри помеченного метода (или класса) выполняются в рамках одной транзакции и либо целиком фиксируются (commit), либо при ошибке откатываются (rollback). Аннотация применяется на уровне метода или класса.
Как это работает подробнее
Spring оборачивает бин в AOP-прокси. Когда помеченный метод вызывается через этот прокси, Spring перед вызовом открывает транзакцию — берёт соединение из пула — а после успешного завершения метода выполняет commit. Если метод бросает исключение, транзакция откатывается, и база данных остаётся в согласованном состоянии.
- Откат по умолчанию: происходит только при непроверяемых исключениях —
RuntimeExceptionиError. - Checked-исключения: если метод бросает проверяемое исключение, нужно явно указать
rollbackFor, например@Transactional(rollbackFor = Exception.class). - Self-invocation: когда один метод бина вызывает другой
@Transactional-метод того же бина черезthis, вызов идёт в обход прокси, и новая транзакция не открывается. - Дополнительные настройки: через аннотацию можно задавать распространение транзакции (propagation), уровень изоляции (isolation) и другие параметры.
Пример кода
OrderService.java
@Service
public class OrderService {
private final OrderRepository orderRepository;
public OrderService(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
@Transactional
public void placeOrder(Order order) {
orderRepository.save(order);
// если здесь возникнет RuntimeException, транзакция откатится
}
}