Как моделировать Java EE?

Скажем, я решил пойти со стеком Java EE для своего корпоративного приложения.

Теперь, для моделирования домена (или: для проектирования M MVC), какие API-интерфейсы я могу смело предположить и использовать, и от чего я должен держаться подальше от... скажем, через слой абстракции?

Например,

  • Должен ли я идти и мутировать мою модель вызовами Hibernate/JPA API? Или я должен построить абстракцию... свой собственный уровень сохранения, чтобы избежать жесткого кодирования этих двух конкретных API устойчивости? Почему я спрашиваю об этом: Несколько лет назад появился этот API-интерфейс Kodo, который был заменен Hibernate. Если бы кто-то разработал слой persistence и закодировал остальную часть модели на этом уровне (вместо того, чтобы заманивать модель на вызовы конкретному API-интерфейсу поставщика), это позволило бы (относительно) легко переключиться с Kodo на Hibernate на xyz.

  • Рекомендуется ли агрессивное использование * QL, предоставленного поставщиком персистентности в вашей модели домена? Я не осведомлен о каких-либо реальных проблемах (например, производительности, масштабируемости, переносимости и т.д.), Возникающих из-за интенсивного использования языка, подобного HQL. Почему я спрашиваю об этом: Я хотел бы как можно больше избегать написания собственного кода, когда то же самое можно было бы выполнить с помощью языка запросов, который более переносимый, чем SQL.

Извините, но я полный новичок в этой области. Где я могу найти дополнительную информацию по этой теме?

Ответ 1

Вот что я считаю традиционным:

  • Объекты вашего проекта образуют модель домена. Они должны быть повторно использованы и не тесно связаны с технологией персистентности (я вернусь позже о плотной и свободной связи).
  • Бизнес-уровень использует модель домена, но также предоставляет услуги и другие продукты.
  • Уровень доступа к данным отвечает за сохранение модели домена (сущностей) в постоянном хранилище.

Сущность не должна напрямую обращаться к уровню доступа к данным. Но бизнес-уровень будет таким образом, чтобы загружать и сохранять объекты модели домена.

Если вы сопоставляете это с технологиями Java EE, вы обычно получаете что-то вроде:

  • Объекты → POJO с аннотациями Hibernate/JPA. Обратите внимание, что аннотации не подразумевают жесткой связи с JPA/Hibernate, тот же POJO может использоваться где-то еще без Hibernate.
  • Бизнес-уровень → Session EJB или Spring
  • Уровень доступа к данным → JPA/Hibernate

Это грубый эскиз и есть много возможных вариантов. Вы можете пропустить сессию EJB и реализовать бизнес-уровень другим способом. Вы также можете решить, чтобы бизнес-уровень вызывал сессию JPA/Hibernate Session/EntityManager напрямую, и в этом случае JPA/Hibernate действительно является DAL, или вы можете захотеть обернуть доступ к Session/EntityManager в так называемые объекты доступа к данным (DAO).

Что касается HQL, попробуйте придерживаться того, что переносится, и если вы используете собственный SQL, следуйте соглашениям SQL-92. Если материал станет сложным, возможно, представите DAO. Таким образом, вы знаете, что единственное место, где есть запросы HQL, находится в DAO. Вы также можете сначала реализовать логику запроса "процедурно" в DAO, и если у вас есть проблемы с производительностью, повторите ее реализацию с помощью более сложного запроса HQL.

ИЗМЕНИТЬ

Относительно ваших вопросов в комментарии:

Бизнес-уровень зависит от уровня данных. Если вы хотите, чтобы бизнес-уровень не зависел от Hibernate/JPA, тогда ваш уровень данных должен абстрагироваться от Hibernate/JPA. Если вы используете DAO для своего уровня данных, это будет так. DAO будет "тонким рукописным слоем персистентности над Hibernate" (чтобы взять ваши слова). Я бы представил DAO для всех объектов в вашем случае.

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

Тем не менее, вот список ресурсов, которые могут вас заинтересовать: книги Структура архитектуры корпоративных приложений, книга Real World Java EE Patterns - переосмысление лучших практик, книга Разработка домена Driven и более конкретно шаблоны Объект доступа к данным, Паттерн репозитория, Открыть сеанс в режиме просмотра (если это для веб-приложения) и, возможно, Модель анемичного домена.

РЕДАКТИРОВАТЬ 2

Хорошо, еще несколько предложений о транзакциях:

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

С EJB3 транзакции могут быть объявлены аннотациями и приложением. сервер управляет этим для вас. Дополнительную информацию см. В этом другом ответе. С помощью Spring вы можете также объявить транзакции декларативно, но я не знаю деталей. В противном случае вам нужно будет начать/остановить транзакцию самостоятельно. Это будет немного отличаться от того, используете ли вы транзакции JDBC или транзакции JTA.

Транзакции также относятся к ленивой загрузке в Hibernate/JPA. Объект, который был ленивым загружен, действительно может быть загружен только в случае текущей транзакции. Если транзакции завершаются на бизнес-уровне, объекты, которые возвращаются на уровень представления, должны быть загружены с высокой нагрузкой.

Чтобы обойти эту проблему, популярным шаблоном для веб-приложений является Открыть сеанс в представлении, о котором я уже говорил. В этом случае слой презентации запускает/останавливает транзакции (что немного неверно концептуально), но отлично работает с ленивой загрузкой.

Ответ 2

Ваша модель домена и ее уровень сохранения должны теоретически быть раздельными - нет необходимости в классе с именем Entity знать что-либо о том, если и как оно сохраняется, поэтому вы можете использовать что-то вроде Hibernate для создания уровня персистентности без загрязняя сами классы модели домена. Вы не "кодируете модель [...] против этого слоя" - вы кодируете модель, а затем сопоставляете ее с постоянным хранилищем с каким-то уровнем ORM, где модель домена не зависит от уровня ORM. Очевидно, что уровень сохранения будет зависеть от модели домена, но это хорошо.

Я лично боюсь слишком много использовать HQL с (N) Hibernate по той причине, о которой вы просите, но бывают случаи, когда это неизбежно. Вы уже знаете и сами подчеркнули, что главный вопрос там, так что вы вряд ли все равно злоупотребляете этим.