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)


Есть вариант поменять propagation на REQUIRES_NEW. В этом случае PersonValidateService.validateName будет выполнен в отдельной транзакции. Так что родительская не будет отменена.
  @Transactional(propagation = Propagation.REQUIRES_NEW)

src: habr

https://habr.com/ru/post/567368/


Комментарии

Популярные сообщения из этого блога

kafka конспект однако

Дэвид Рок: Ваш мозг на работе - Разговоры в Гугле

Отслеживание Процесса загрузки с PHP и JavaScript