これが私が伝統的な見方であると信じているものです:
- プロジェクト内のエンティティがドメイン モデルを形成します。それらは再利用可能で、永続化テクノロジに密結合されていない必要があります (密結合と疎結合については後で説明します)。
- ビジネス層は、ドメイン モデルを使用しますが、サービスやその他のものも公開します。
- データ アクセス レイヤーは、ドメイン モデル (エンティティ) を永続的なストアに永続化する役割を果たします。
エンティティは、データ アクセス層を直接呼び出すべきではありません。しかし、ビジネス レイヤーは、ドメイン モデルのエンティティを読み込んで永続化する方法で行います。
それを Java EE テクノロジーにマッピングすると、通常は次のようになります。
- エンティティ --> Hibernate/JPA アノテーション付きの POJO。注釈は、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 クエリを使用して再実装することもできます。
編集
コメントでの質問について:
ビジネス層はデータ層に依存します。ビジネス層が Hibernate/JPA に依存しないようにする場合は、データ層で Hibernate/JPA を抽象化する必要があります。データ層に DAO を使用する場合は、これに該当します。DAO は、「Hibernate 上の薄い手書きの永続化レイヤー」になります (あなたの言葉を借りれば)。あなたの場合、すべてのエンティティにDAOを導入します。
あなたが求めているのは、かなり一般的な設計上の質問です。そのための決定的なレシピを提供することはできません。また、ケースバイケースであるため、すべてのバリエーションを 1 つの回答にまとめることもできません。たとえば、トランザクションの問題についてはこれまで説明してきませんでした。通常はビジネス レイヤーから開始しますが、データ レイヤーは認識しておく必要があります。これは通常、使用するテクノロジーと要件によって異なります。
それでも、興味のあるリソースのリストは次のとおりです。本Pattern of Enterprise Application Architecture、本Real World Java EE Patterns - Rethinking Best Practices、本Domain Driven Design、より具体的にはパターンData Access Object、Repository pattern、Open Session in View (Web アプリの場合)、そしてAnemic Domain Modelかもしれません。
編集2
では、トランザクションに関する文をいくつか追加します。
トランザクションは、概念的にはビジネス レイヤーで管理する必要があります。一貫性を保つために 1 つの作業単位で何を行う必要があるかの定義は、アプリケーションのロジックそのものに依存します。
EJB3 では、アノテーションとアプリでトランザクションを宣言できます。サーバーがそれを管理します。詳細については、この他の私の回答を参照してください。Spring では、トランザクションを宣言的にマークすることもできますが、詳細はわかりません。それ以外の場合は、自分でトランザクションを開始/停止する必要があります。これは、JDBC トランザクションを使用するか JTA トランザクションを使用するかによって少し異なります。
トランザクションは、Hibernate/JPA での遅延読み込みにも関連しています。遅延ロードされたエンティティは、現在のトランザクションがある場合にのみロードできます。トランザクションがビジネス レイヤーで終了した場合、プレゼンテーション レイヤーに返されるエンティティは熱心に読み込まれる必要があります。
この問題を回避するために、Web アプリケーションの一般的なパターンは、既に述べたOpen Session in Viewです。この場合、プレゼンテーション レイヤーはトランザクションを開始/停止しますが (これは概念的には少し間違っています)、遅延読み込みで問題なく動作します。