Проект и транзакции, управляемые доменом, в среде Spring
Я использовал для разработки моего приложения вокруг модели анемичного домена, поэтому у меня было много объектов репозитория, которые были введены на большой, толстый, уровень обслуживания, ориентированный на транзакцию. Этот шаблон называется Transaction script. Это не считается хорошей практикой, так как это приводит к процедурному коду, поэтому я хотел перейти к проекту, управляемому доменом.
После прочтения нескольких статей в Интернете, слушая разговор Криса Ричардсона на Parley и читающий главы DDD в POJO в действии, я думаю, что получил большую картину.
Проблема в том, что я не знаю, как организовать транзакции в моем приложении. Чис Ричардсон в своей книге гласит:
Уровень представления обрабатывает HTTP-запросы из браузера пользователей путем вызова модель домена прямо или косвенно через фасад, который, как я описанный в предыдущей главе, является либо POJO, либо EJB.
До сих пор хорошо, но Шрини Пенчикала на В статье InfoQ говорится:
Некоторые разработчики предпочитают управлять транзакциями в классах DAO, который является плохим дизайном. Это приводит к слишком тонкому управлению транзакциями, что не дает гибкости в управлении вариантами использования, когда транзакции охватывают несколько доменных объектов. Сервисные классы должны обрабатывать транзакции; таким образом, даже если транзакция охватывает несколько доменных объектов, класс обслуживания может управлять транзакцией, поскольку в большинстве случаев использования класс Service обрабатывает поток управления.
Хорошо, поэтому, если я правильно это понимаю, классы репозитория не должны быть транзакционными, уровень обслуживания (который теперь намного тоньше) является транзакционным (как это было в шаблоне Transaction script). Но что, если объекты домена вызываются через слой представления напрямую? Означает ли это, что мой объект домена должен иметь транзакционное поведение? И как реализовать его в среде Spring или EJB?
Это кажется странным для меня, поэтому я был бы счастлив, если бы кто-нибудь разъяснил это. Спасибо.
Ответы
Ответ 1
Мое личное применение DDD с Spring и Hibernate до сих пор заключается в том, чтобы иметь уровень обслуживания транзакций без состояния и доступ к объектам домена через него. Так, как я это делаю, модель домена вообще не знает о транзакциях, которая полностью обрабатывается службами.
Существует пример приложения который может оказаться полезным для ознакомления. Похоже, Эрик Эванс был вовлечен в его создание.
Ответ 2
Смотрите этот чрезвычайно полезный блог-пост. В нем объясняется, как добиться плавного DDD, не теряя возможности Spring и JPA. Он сосредоточен вокруг аннотации @Configurable
.
Мое мнение по этим вопросам немного непривычно. Анемическая модель данных на самом деле не ошибается. Вместо того, чтобы иметь один объект с операциями data +, у вас есть два объекта: один с данными и один с операциями. Вы можете рассматривать их как один объект - то есть, удовлетворяющий DDD, но для удобства использования они физически разделены. Логически они одинаковы.
Да, это разрушает инкапсуляцию, но для достижения ваших целей вам не нужно использовать "волшебство" (aop + java agent).
Что касается транзакций - есть что-то, называемое "Транзакционное распространение". Spring поддерживает его с помощью @Transactional(propagation=Propagation.REQUIRED)
.
См. это пункт 9.5.7. Если вы хотите, чтобы ваши транзакции охватывали несколько методов (из нескольких объектов), вы можете соответствующим образом изменить атрибут распространения.
Вы также можете использовать @Transactional
в своем сервисе, где это необходимо, но это может привести к множеству сервисных классов для котельных в тех случаях, когда вы хотите использовать простые одношаговые операции, такие как "сохранить".
Ответ 3
Я думаю, что один простой способ начать работу с DDD и Spring и иметь хорошие примеры того, как работать с транзакциями, - это посмотреть на один из примеров приложений, которые поставляются с Spring Roo. Roo выдает код, который следует принципам DDD. Он в значительной степени зависит от AspectJ. Я подозреваю, что это было реализовано на основе идей, выдвинутых (еще в 2006 году) одним из весовых весов SpringSource, Рамнивасом Ладдадом, в этом разделе.