Ответ
Spring фиксирует (коммитит) транзакцию после успешного выполнения метода, помеченного @Transactional. Если в методе не возникло исключений, приводящих к откату, Spring вызывает commit у менеджера транзакций.
Механизм работы:
- Перед вызовом метода Spring открывает транзакцию (или присоединяется к существующей).
- Метод выполняется в контексте этой транзакции.
- Если метод завершился нормально → Spring коммитит транзакцию.
- Если выброшено исключение → Spring проверяет, нужно ли делать rollback.
Правила отката (rollback) по умолчанию:
- Откат происходит: При
RuntimeExceptionи его наследниках (например,NullPointerException,IllegalArgumentException). - Откат НЕ происходит: При
checkedисключениях (например,IOException,SQLException).
Управление поведением:
// Откат при любом Exception (включая checked)
@Transactional(rollbackFor = Exception.class)
public void saveData() throws IOException {
// ...
}
// НЕ откатывать при определенном RuntimeException
@Transactional(noRollbackFor = IllegalArgumentException.class)
public void updateEntity() {
// ...
}
Практический пример:
@Service
public class TransferService {
@Transactional // Транзакция откроется здесь
public void transfer(Account from, Account to, BigDecimal amount) {
from.debit(amount); // Изменения в памяти
to.credit(amount); // Изменения в памяти
// Если здесь выбросится RuntimeException -> ROLLBACK
// Если исключений нет -> COMMIT после выхода из метода
}
}
Важно: Фиксация в БД происходит именно в момент коммита, а не после каждого вызова метода внутри транзакции.