Вот что я считаю традиционным взглядом:
- Объекты в вашем проекте образуют модель домена. Они должны быть многоразовыми и не должны быть тесно связаны с технологией персистентности (я позже вернусь к проблеме жесткой и слабой связи)
- Бизнес-уровень, использует модель предметной области, но также предоставляет сервисы и другие материалы.
- Уровень доступа к данным отвечает за сохранение модели домена (сущностей) в постоянном хранилище.
Сущность не должна вызывать уровень доступа к данным напрямую. Но бизнес-уровень будет таким образом загружать и сохранять сущности модели предметной области.
Если вы сопоставляете это с технологиями Java EE, вы обычно получаете что-то вроде:
- Сущности -> POJO с аннотациями Hibernate / JPA. Обратите внимание, что аннотации не предполагают тесной связи с JPA / Hibernate, тот же POJO может использоваться где-то еще без Hibernate.
- Бизнес-уровень -> Сеанс EJB или Spring
- Уровень доступа к данным -> JPA / Hibernate
Это грубый набросок, и существует множество возможных вариантов. В частности, вы можете пропустить сессионный EJB-компонент и реализовать бизнес-уровень другим способом. Вы также можете решить, чтобы бизнес-уровень вызывал JPA / Hibernate Session / EntityManager напрямую, в этом случае JPA / Hibernate действительно является DAL, или вы можете захотеть обернуть доступ к Session / EntityManager в так называемые объекты доступа к данным (DAO ).
Что касается HQL, попробуйте придерживаться того, что является переносимым, и, если вы используете собственный SQL, следуйте соглашениям SQL-92. Если вещи усложняются, может быть, ввести DAO. Таким образом, вы знаете, что единственное место, где есть HQL-запросы, это DAO. Вы также можете сначала внедрить логику запроса «процедурно» в DAO, и, если у вас есть проблемы с производительностью, повторно реализовать ее с помощью более сложного запроса HQL.
EDIT
По поводу ваших вопросов в комментарии:
Бизнес-уровень зависит от уровня данных. Если вы хотите, чтобы бизнес-уровень не зависел от Hibernate / JPA, то вашему уровню данных необходимо удалить abstract Hibernate / JPA. Если вы используете DAO для своего уровня данных, это будет иметь место. DAO будет «тонким рукописным постоянным слоем над Hibernate» (если принять ваши слова). Я бы представил DAO для всех организаций в вашем случае.
То, что вы спрашиваете, является довольно общим вопросом о дизайне. Я не могу дать однозначного рецепта для этого и, возможно, суммировать все варианты в одном ответе, поскольку это зависит от конкретного случая. Например, мы пока не говорили о проблеме транзакций, которую вы обычно начинаете на бизнес-уровне, но об этом должен знать уровень данных. Обычно это зависит от используемых технологий и ваших требований.
Тем не менее, вот список ресурсов, которые могут вас заинтересовать: книги Шаблон архитектуры корпоративных приложений , книга Шаблоны реального мира Java EE - переосмысление передового опыта , книга Домен-управляемый дизайн и, в частности, шаблоны Объект доступа к данным , Шаблон репозитория , Открыть сеанс в представлении (если это для веб-приложение) и, возможно, Модель анемичного домена .
РЕДАКТИРОВАТЬ 2
Хорошо, еще несколько предложений о транзакциях:
Транзакции должны концептуально управляться на бизнес-уровне; определение того, что нужно сделать в одной единице работы, чтобы быть последовательным, действительно зависит от самой логики приложения.
С EJB3 транзакции могут быть объявлены с аннотациями и приложением. Сервер управляет этим для вас. См. этот другой ответ моего для получения дополнительной информации. С Spring вы также можете пометить транзакции декларативно, но я не знаю деталей. В противном случае вам нужно будет начать / остановить транзакцию самостоятельно. Это будет немного отличаться, используете ли вы транзакции JDBC или транзакции JTA.
Транзакции также относятся к отложенной загрузке в Hibernate / JPA. Сущность, которая была загружена с отложенной загрузкой, действительно может быть загружена только при наличии текущей транзакции. Если транзакции завершаются на бизнес-уровне, сущности, которые возвращаются на уровень представления, должны быть загружены с нетерпением.
Чтобы обойти эту проблему, популярным шаблоном для веб-приложений является Open Session in View , о котором я уже упоминал. В этом случае уровень представления запускает / останавливает транзакции (что концептуально немного неверно), но прекрасно работает с отложенной загрузкой.