1

私は、多数のクライアントにバックエンド機能を提供する Java EE アプリケーションを担当しています。一部のクライアントも Java で記述されているため、サーバーとクライアントが共有する別の jar にエンティティを抽出しました。

サーバーは永続性のために JPA2 を使用し、クライアントとの通信には JAX-RS を使用し、XML および JSON との間のシリアル化には JAXB を使用します。その結果、(共有) クラス ファイルには、JPA アノテーションと JAXB アノテーションの両方が含まれます。

明らかに、同じオブジェクトがサーバー (マネージド JPA エンティティ) とクライアント (デシリアライズされた POJO) では動作が異なります (特に 1 対多の関係に関して)。

質問:個々のメソッド呼び出しが実行される場所に応じて異なる動作をさせたい場合があります。同じクラスの 2 つの実装を手動で維持する必要がないように、継承によってこれを解決できますか?

例:

  • チームには多くのプレーヤーがいます。選手には名前があります。
  • GET /team/<id>リクエストは、チームを取得するため、およびチームGET /team/<id>/<playerName>の特定のプレーヤーを取得するためにマップされます。
  • マーシャリングとシリアライゼーションの場合、Teamは「フラット」のままでなければなりません (プレーヤーを含めないでください)。ただし、シリアライゼーションに名前を含めて、取得できるプレーヤーをクライアントが詳細に把握できるようにします。

サーバー側では、次のように構築します。

@Entity
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Team {

  /* some other fields, belonging to the Team */

  @OneToMany(fetch = FetchType.LAZY, mappedBy="team")
  @XmlTransient  // don't marshall the players
  List<Player> players;

  /* getters and setters as necessary */

  @XmlElement
  public List<String> getPlayerNames() {
    List<String> names = new ArrayList<String>();
    for (Player p : getPlayers()) {
      names.add(p.getName());
    }
    return names;
  }
}

クライアント側では、次のようにマッピングします。

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Team {

  /* some other fields, belonging to the Team */

  List<String> playerNames;

  public List<String> getPlayerNames() {
    return playerNames;
  }

  public void setPlayerNames(List<String> playerNames) {
    this.playerNames = playerNames;
  }

  /* getters and setters as necessary */

}

このようにして、プレイヤー名はサーバー側で( @XmlElement-annotatedを介して) マーシャリングされます。getPlayerNames()クライアントがそれを受け取ると、リストを適切にアンマーシャリングします。誰もが幸せです。

ただし、今では、2 つの本質的に同一のクラスを維持する必要がありますが、わずかな違いしかありません...これを適切に行うための最良の方法は何ですか?

4

1 に答える 1

1

エンティティを直接シリアライズしてネットワーク経由で送信すると、問題が発生する可能性があります。たとえば、循環参照がある場合や、特に JSON でデシリアライズに必要な追加情報を含めたい場合などです。もう 1 つの問題は、分離されたエンティティ (エンティティをクライアントに送信すると、エンティティ マネージャーがエンティティの制御を失い、エンティティが戻ってきたときにエンティティを再接続する必要がある) または遅延ロード (クライアントで遅延ロードできない) である可能性があります。したがって、ネットワーク上でエンティティを送信する前に、エンティティをデータ転送オブジェクトに変換することをお勧めします。詳細と動機については、Fowler の著書 Patterns of Enterprise Application Architecture (401 ページ、ほとんどの章は Google ブックスから入手できます) を参照してください。

クライアントとサーバーで同じクラスを使用することも、動作が異なり、将来さらに分岐する可能性があるため、問題になる可能性があります。クライアントとサーバーで同一のコード ベースにコミットすることで自分自身を制限したり、大きな混乱に陥ったりする可能性があります。

于 2012-05-31T09:35:32.907 に答える