5

Где находится аннотация @Transactional?

11

Следует ли размещать аннотацию @Transactional в классах DAO и/или их методах, или лучше аннотировать классы Service, использующие объекты DAO? Или имеет смысл аннотировать оба уровня?

5 ответ(ов)

6

На мой взгляд, транзакции должны находиться на уровне сервисов. Именно этот уровень знает о единицах работы и бизнес-кейсах. Это правильный подход, особенно если у вас есть несколько DAO, внедренных в сервис, которые должны работать вместе в рамках одной транзакции.

3

В общем, я согласен с другими, которые утверждают, что транзакции обычно начинаются на уровне сервиса (в зависимости от требуемой вам гранулярности, конечно).

Однако я также начал добавлять аннотацию @Transactional(propagation = Propagation.MANDATORY) на уровень DAO (а также на другие слои, где запуск транзакций не разрешен, но требуются существующие), поскольку это значительно упрощает обнаружение ошибок, когда вы забыли начать транзакцию в вызывающем методе (например, на уровне сервиса). Если ваш DAO аннотирован с обязательной пропагандой, вы получите исключение, указывающее на отсутствие активной транзакции при вызове метода.

Кроме того, у меня есть интеграционное тестирование, где я проверяю все бины (post processor бинов) на наличие этой аннотации и проваливаю тест, если в бине, который не принадлежит сервисному слою, имеется аннотация @Transactional с пропагацией, отличной от Mandatory. Таким образом, я удостоверяюсь, что мы не начинаем транзакции на неправильном уровне.

1

Аннотации @Transactional следует применять ко всем операциям, которые являются неделимыми.

Например, у вас есть вызов "сменить пароль". Это действие состоит из трех операций:

  1. Изменить пароль.
  2. Провести аудит изменения.
  3. Отправить клиенту уведомление о том, что пароль был изменен.

В данном случае, если не удается провести аудит, следует ли также откатить изменение пароля? Если да, то аннотация @Transactional должна обрамлять только первые две операции (то есть на уровне сервисов). А если не удастся отправить электронное письмо (что, вероятно, не должно произойти, если у вас есть встроенные механизмы обработки ошибок), следует ли откатить изменение пароля и аудит?

Эти вопросы важно задавать при решении о том, где разместить аннотацию @Transactional.

0

Обычно аннотации следует добавлять на уровне сервисного слоя, но это в значительной степени зависит от ваших требований.

Аннотирование на уровне сервисов приведет к более длительным транзакциям по сравнению с аннотированием на уровне DAO. В зависимости от уровня изоляции транзакций это может вызвать проблемы, так как параллельные транзакции не будут видеть изменения друг друга, например, при уровне REPEATABLE READ.

Аннотирование на уровне DAO позволит свести транзакции к минимуму, но при этом функциональность, предоставляемая вашим сервисом, не будет выполнена в одной (откатной) транзакции.

Таким образом, если режим распространения установлен по умолчанию, нет смысла аннотировать оба уровня.

0

Да, имеет смысл аннотировать оба уровня — и уровень сервиса, и уровень DAO. Аннотирование уровня DAO позволяет обеспечивать, что методы DAO всегда вызываются из уровня сервиса с установленным режимом "mandatory". Это добавляет ограничение на возможность вызова методов DAO напрямую из UI-уровня или контроллеров, что помогает сохранять чистую архитектуру приложения.

Кроме того, если вам нужно протестировать уровень DAO в частности, аннотация DAO уровня поможет убедиться, что он тестируется с учетом функциональности транзакций. Таким образом, вы сможете гарантировать, что тесты на уровне DAO выполняются в контексте транзакций, что очень важно для сохранения целостности данных.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь