2

現在、次のコンポーネントを使用して分散アプリケーションに取り組んでいます。

1.層: データベース サーバー -> MySQL 5.5

2.層: アプリケーション サーバー -> Glassfish 3.1.2.2

3.層: スタンドアロン Fat-Client -> Java-SE (JRE 6)

JPA 2.0 (eclipse-link) を永続化プロバイダーとして使用し、現在、シリアル化を使用して第 2 層と第 3 層の間で @Entity Bean を渡しています。JPA でサポートされている遅延フェッチを利用するために、静的ウィービングを使用します。

私の問題は、第 2 層と第 3 層の間のシリアル化のために遅延フェッチが機能しないことです。エンティティ Bean の 1 つをシリアル化するたびに、ネットワーク経由で送信する前に他のエンティティ/テーブルとのすべての関係を取得する必要があるため、ネットワーク トラフィックが大量に発生します。

このようなセットアップで JPA 遅延フェッチを利用するにはどうすればよいですか? 軽量の DTO/DAO を導入する必要のない回避策はありますか (これにより、プロジェクトが非常に複雑になります)。

事前にご協力いただきありがとうございます。

4

2 に答える 2

3

同様のアーキテクチャでの私の経験では、非常に大きなプロジェクトの場合、DTO は避けられず、必要に応じて使用する必要があります。

特に他のエンティティとの複数の関連付けがある場合、切り離されたエンティティを操作すると、データベースのロードとシリアライゼーションによるパフォーマンスの問題が発生するだけでなく、非常に複雑になります。実際、コードが十分に文書化されていない限り、特定のアソシエーションがロードされているかどうかをプレゼンテーション層で知るのは難しく、遅延初期化例外が大量に発生します。

シリアル化された切り離されたエンティティをプレゼンテーション層からサービス層に送り返すと、さらに悪いことに、切り離されたエンティティと付加されたエンティティを組み合わせて使用​​するコードになり、事態がさら​​に複雑になります。

したがって、私のアドバイスは次のようになります。

  • エンティティが単純であり、UI レイヤーが読み込まれた関連付けをあまり必要としない場合は、エンティティをサービス レイヤーから UI レイヤーに転送します。どの関連付けが初期化され、どの関連付けが初期化されていないかを常に文書化します。関連付けが多すぎる場合は、DTO とアドホック クエリを使用して、データベースから必要なデータを読み込みます。
  • 多数のエンティティが必要な場合 (たとえば、O(100) 以上の結果を返す検索フォームの結果など)、DTO をサービス層から UI 層に転送します。アドホック クエリを使用して、要求されたデータを読み込みます。
  • エンティティをプレゼンテーション レイヤーからサービス レイヤーに転送することは避けてください。その場合、サービス レイヤーで最初に行うことは、エンティティの添付バージョンをデータベースから再読み込みするか、受信したエンティティをマージして、添付エンティティを常に操作できるようにすることです。サービス層でスローされた遅延初期化例外のデバッグと、前の画面によって数分前にロードされた切り離されたエンティティの使用による原因をデバッグすることは、楽しいことではありません。
于 2012-09-22T11:53:54.820 に答える
0

特定のクエリでフェッチする必要があるリレーションの深さを定義するために、ロード グループとクエリ ヒントを使用することで、この問題を解決しました。JPA プロバイダーとして eclipse-link を使用する場合、これには遅延フェッチとウィービングが必要です。

以下に短い例を示します。

特定のファサードに対するサーバー側のクエリ:

@Override
public List<Contact> query(LoadGroup group) {
    TypedQuery<Contact> query = em.createQuery("SELECT c FROM Contact c", Contact.class);
    if(group!=null) { query.setHint(QueryHints.LOAD_GROUP, group); }
    return query.getResultList();
}

その特定のファサードに対するクライアント側のクエリ:

LoadGroup group = new LoadGroup();
group.addAttribute("telephone");
group.addAttribute("address.street");
List<Contact> contacts = remoteContactFacade.query(group);

この例では、Contact テーブルには、Address テーブルと Telephone テーブルとの多対 1 の関係があります。ドット表記を使用することで、取得する対象の深さを定義できます。

お役に立てれば。

于 2012-10-27T09:52:02.060 に答える