Проект и транзакции, управляемые доменом, в среде 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, Рамнивасом Ладдадом, в этом разделе.