Как стать автором
Обновить

Комментарии 8

Самый простой исправить это — заменить Exception на непроверяемое исключение. Например, NullPointerException

Вы извините, не это говнокод какойто. Сервис пользователей который возвращает NullPointerException? Серьезно? Я бы не хотел иметь с таким API ничего общего.

Дальше, имхо, начинается совсем жесть. Ладно валидатор который ексепшен кидает я еще могу понять, но «Если валидация не проходит, создаем пользователя с именем по умолчанию.» совсем никак. Да, я понимаю, что это примеры, но у новичков такие подходы вполне себе отложатся.

ЗЫ как человек давно не писавший на ява, и не юзающий спринг, немного недоумеваю зачем так стрелять себе в ногу. У меня обычно есть обработчик ексепшенов самого верхнего уровня который по типам смотрит что случилось и в большинстве случаев откатывает транзакцию, если это не нужно то транзакция коммитится/откатывается вручную, все предельно очевидно ясно и красиво.

придирайся к искусственным примерам, введенным для наглядности
@
ругай джаву
@
говори как у тебя всё хорошо

придирайся к искусственным примерам, введенным для наглядности

А я написал на этот счет что и почему.
ругай джаву

Джаву я люблю
говори как у тебя всё хорошо

Так и рождаются best practice

Проблема в том что когда новичок увидит такой пример, для него это будет рабочее решение. И не факт что он сможет понять что так делать нельзя.

НЛО прилетело и опубликовало эту надпись здесь

Поведение @Transactional было скопировано в свое время с JavaEE, в котором многие решения были просто ужасными. В часности, непонятно зачем было выставлять UserTransaction.setRollbackOnly() при выкидывании unchecked exception на каждом прокси (наверное, чтобы как можно раньше откатить и освободить "ценнейший" ресурс), вместо того, чтобы откатывать только на верхнем уровне, если exception не был обработан.

Например, мы можем добавить атрибут noRollbackFor в PersonValidateService.

Это только если экспшн возникает непосредственно в вашем коде, а не ниже по стеку. Стандартная ситуация: работаем с JPA, хотим поставить логику на определенные ошибки, (напр. EntityExistsException). Однако noRollbackFor=PersistenceException.class не сработает, ибо EntityManager уже заботливо выставил setRollbackOnly.

Все проблемы с @Transactional от того, что его слишком просто прилепить на метод в сервисе, и оно даже будет работать. Но управление транзакцией - это не забота сервиса слоя бизнес-логики, этим должен заниматься инфраструктурный фасад, который и должен вызываться из контроллера.

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

Хорошей практикой при реализации бизнес логики является создание собственных классов исключений. При создании такого класса исключения, разработчик путем выбора родительского класса (RuntimeExecption или Exception) как раз и определяет требуется ли откатывать транзакцию при этом исключении или нет. При таком подходе не будет возникать всех вышеописанных проблем по откату транзакций в котлине или java.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории