IKYouRBad

Пользователь

Регистрация: 08.03.2022

Сообщения: 111

Рейтинг: -9

Нарушения: 1000

IKYouRBad

Регистрация: 08.03.2022

Сообщения: 111

Рейтинг: -9

Нарушения: 1000

Что я хочу сделать.


Я хочу, чтобы при запросе на обновление поля сущности проходила определенная валиция.

Я добавил Hibernate interceptor, который это проверяет и выкидывает org.hibernate.CallbackException.

При этом, я хочу чтобы сервис метод был

1. Транзакционным

2. Не происходит роллбэк на эксепшон интерсептора

3. Происходил роллбэк на другие эксепшоны.


То-есть выглядит это так:

Есть транзакционный сервис метод, который в цикле запускает некий метод, который выбрасывает CallbackException после неудачной валидации, но там в транзакции это оборачивается в JpaSystemException, который я ловлю и просто логаю warning. И если поймали - просто переходим на некст итерацию. Если выпадет условный IllegalArgumentException - падаем и роллбэк.

Сейчас это работает когда метод не транзакционный, но тогда не будет роллбэка на другие эксепы.


@Transactional(noRollbackFor = JpaSystemException.class) = не помогает

Че делать?)

Noonecan

Пользователь

Регистрация: 14.03.2014

Сообщения: 1248

Рейтинг: 344

Noonecan

Регистрация: 14.03.2014

Сообщения: 1248

Рейтинг: 344

1. noRollbackFor = {JpaSystemException.class }

2. Стоит ли на каком нибудь конфиги или на самом приложении @EnableTransactionManagement?

3. Есть одна загвоздка, спринг ролбечит только анчекед эксепшены по дефолту, т.е. если твой ексепшн, который выкидывается в процессе работы не extends RuntimeException - то для такого ексепшена никогда не будет ролбека, если хочешь, чтобы твой checked exception отролбечился - сделай на @Transactional rollbackFor


Попробуй может че поможет.


А вообще хендлить консистентность данных при пуше в базу - это прям не круто, обмажь все валидаторами и отсекай пачки данных до того, как пытаешься их впушить в базу, и память сэкономишь и бд к неконсистентному виду никогда не приведешь.


UPD. От коллеги


"По умолчанию ролбэчатся транзакции только в том случае, если RuntimeException покидает границы transactional proxy. Если его покидает Exception, то коммится. " - т.е. грубо говоря, тебе надо выкинуть что нибудь extends RuntimeException выше уровня @Transactional метода, тады ролбекнется. Если выкенешь выше checked exception - закоммитится

IKYouRBad

Пользователь

Регистрация: 08.03.2022

Сообщения: 111

Рейтинг: -9

Нарушения: 1000

IKYouRBad

Регистрация: 08.03.2022

Сообщения: 111

Рейтинг: -9

Нарушения: 1000

Noonecan сказал(а):

1. noRollbackFor = {JpaSystemException.class }

2. Стоит ли на каком нибудь конфиги или на самом приложении @EnableTransactionManagement?

3. Есть одна загвоздка, спринг ролбечит только анчекед эксепшены по дефолту, т.е. если твой ексепшн, который выкидывается в процессе работы не extends RuntimeException - то для такого ексепшена никогда не будет ролбека, если хочешь, чтобы твой checked exception отролбечился - сделай на @Transactional rollbackFor


Попробуй может че поможет.


А вообще хендлить консистентность данных при пуше в базу - это прям не круто, обмажь все валидаторами и отсекай пачки данных до того, как пытаешься их впушить в базу, и память сэкономишь и бд к неконсистентному виду никогда не приведешь.


UPD. От коллеги


"По умолчанию ролбэчатся транзакции только в том случае, если RuntimeException покидает границы transactional proxy. Если его покидает Exception, то коммится. " - т.е. грубо говоря, тебе надо выкинуть что нибудь extends RuntimeException выше уровня @Transactional метода, тады ролбекнется. Если выкенешь выше checked exception - закоммитится

Нажмите, чтобы раскрыть...

CallbackException, как и JpaSystemException - рантаймовые. Я же сказал, что оно работало и сам эксепшон выкидывается.


Noonecan сказал(а):

А вообще хендлить консистентность данных при пуше в базу - это прям не круто, обмажь все валидаторами и отсекай пачки данных до того, как пытаешься их впушить в базу, и память сэкономишь и бд к неконсистентному виду никогда не приведешь.

Нажмите, чтобы раскрыть...

Да хочется так, чтобы любой код, который напишут, который относится к обновлению этого поля - будет валидироваться. Т.е. замена SQL триггера в коде по сути.
А на уровне валидаторов прийдется следить за тем, чтобы каждый написаный код включал в себя код валидации.