spring transaction annotation quirks
По умолчанию Spring откатывает транзакции только в случае непроверяемого исключения. Проверяемые же считаются «восстанавливаемыми» из-за чего Spring вместо rollback
делает commit
. Поэтому personRepository.count()
возращает 2
.
Самый простой исправить это — заменить Exception
на непроверяемое исключение. Например, NullPointerException
. Либо можно переопределить атрибут rollbackFor
у аннотации.
Когда какой-нибудь bean указывает транзакционный сервис в качестве DI зависимости, Spring на самом деле внедряет прокси.
Параметр propagation
у @Transactional
по умолчанию имеет значение REQUIRED
. Это значит, что новая транзакция создается, если она отсутствует. Иначе выполнение продолжается в текущей. Так что в нашем случае весь запрос выполняется в рамках единственной транзакции.
Однако здесь есть нюанс. Если RuntimeException
был выброшен из-за границ transactional proxy, то Spring отмечает текущую транзакцию как rollback-only. Здесь у нас именно такой случай. PersonValidateService.validateName
выбросил IllegalArgumentException
. Transactional proxy выставил флаг rollback
. Дальнейшие операции уже не имеют значения, так как в конечном итоге транзакция не закоммитится.
Я: ежели в одном методе transactional вызвали другой метод помеченный transactional и выкинули catchable exception то транзакция тк она в прокси уже маркируется rollback-only.
Каково решение проблемы? Вообще их несколько. Например, мы можем добавить атрибут noRollbackFor в PersonValidateService.
@Transactional(noRollbackFor = IllegalArgumentException.class)
src: habr
https://habr.com/ru/post/567368/
Комментарии
Отправить комментарий