web-dev-qa-db-ja.com

JPAのパターン:エンティティからデータ転送オブジェクトDTOを生成し、DTOをデータベースにマージする

JPAエンティティからデータ転送オブジェクト(DTO)を作成したり、その逆を行うための良い方法を探しています。 DTOをJSONとしてクライアントに送信し、変更されたDTOを受信して​​データベースに保存します。 JSONからそのJavaクラスに解析された後、受信したオブジェクトのEntityManagerからmergeメソッドを実行するのが最も簡単です。

たとえば、次のエンティティと、変更されたオブジェクトを保存するためのRestメソッドがあります。


@Entity
@Table(name="CUSTOMER")
public class Customer {
    @Id
    Long id;
    @Version
    Long version;
    String name;
    String address;
    String login;
    String password;
    String creditCardNumber;
    @OneToMany(cascade = CascadeType.ALL)
    List<Foo> fooList;

    ... Getter() and Setter()
}

private EntityManager em;
@POST
@Path("/saveCustomer")
public void saveCustomer ( Customer  customer)   {               
   em.merge(customer);
   return;
}  

Entity Class全体をJSONとして送信し、Entity全体を受信する限り、これは正常に機能します。次に、EntityManagerは変更されたオブジェクトをデータベースにマージします。しかし、エンティティのサブセットのみを提供したい場合(顧客の名前と住所のみなど)、問題が発生します。

  1. エンティティのサブセットを作成する最良の方法は何ですか?

    -エンティティのDTOを手動で作成していますか?これにより、エンティティのすべてのサブセットに対して重複したコードが生成されます。これは維持する必要があります。

  2. エンティティのサブセットであるDTOをデータベースにマージする方法は?

    -EntityManagerのmerge()メソッドの使用は機能しません。最初、DTOはエンティティではないため、マージできません。また、DTOからエンティティを作成するだけで、エンティティにいくつかの未設定の値が含まれます。マージ後、値はデータベースでNULLになります。


私が思いついたアイデアの1つは、エンティティに設定したいサブセットごとに追加のエンティティを指定することでした。 (データベースビューのように)これは重複したコードですが、データベースへのDTOのマージに関する問題を解決できます。 (そしておそらくこのコードは自動生成できる)

たとえば、Entity CustomerView1はCustomerクラスと同じテーブルにリンクしていますが、提供するのは顧客の名前と住所のみです。これは実際のCustomerクラスのDTOであり、JSONとして送信してサーバーの外部で変更できます。このクラスは、EntityManagerによってデータベースにマージすることもできます。

@Entity
@Table(name="CUSTOMER")
public class CustomerView1 {
    @Id
    Long id;
    @Version
    Long version;
    String name;
    String address;
    
        ... Getter() and Setter()
}    

しかし、私はこの解決策に疑問を持っています。これがJPAのエンティティーのキャッシングを混乱させ、いくつかの問題を引き起こす可能性があるかどうかはわかりません。


私の質問は、DTOのコード重複を解決し、DTOをデータベースにマージするパターンはありますか?

または、この目的のためのライブラリはありますか? -DTOの自動生成や実際のEntityへのDTOのコピーなど、EntityManagerとのマージを可能にするもの。

17
user3170740

エンティティとDTOのサイズの違いがそれほど大きくない場合は、エンティティの送信を選択できます。

DTOを使用する場合、 失われた更新 などの同時実行性の問題を克服するには、エンティティバージョンをDTOに組み込む必要があります。

エンティティバージョンを使用せず、基になる行がREST GETメソッドとPUTメソッドの間で変更された場合、エンドユーザーが実際に認識していなかった変更をオーバーライドします。

エンティティ(作成、更新、削除)を変更する必要があるときはいつでも、 JPAおよびHibernateオプティミスティックロックメカニズム に依存します。

UIリスト、テーブル、検索結果のDTOは、元のエンティティの予測にのみ関心があるため、実行可能なオプションです。このようにして検索を高速化し、JPAでサポートされていない他のSQL機能(ウィンドウ関数)を利用できます。

4
Vlad Mihalcea

あなたが説明しているような音は、まさに Blaze-Persistence Entity Views が作成されたものです。現在のリリースでは、読み取りモデル、つまりクライアントに送信するモデルの作成のみがサポートされていますが、モデルの書き込み部分はほぼ完了しています。エンティティビューは、インターフェイス/抽象クラスのDTO表現とエンティティモデルをマッピングします。ライブラリは、あらゆる種類のパフォーマンス最適化を実装するために、マッピング情報を最大限に活用します。

0

問題に直接対処するValue Objectデザインパターンを見てください。

このチュートリアルでは、値オブジェクトを紹介します。

http://www.javastuff.in/2012/04/value-object-pattern.html

0
Diversity