web-dev-qa-db-ja.com

どのJava JPAコレクションにタイプを使用しますか?その理由は?

次のコレクションタイプのうち、JPAドメインモデルで使用するものとその理由:

  • Java.util.Collection
  • Java.util.List
  • Java.util.Set

これにはいくつかの基本的なルールがあるのか​​と思っていました。

[〜#〜] update [〜#〜]SetListの違いを知っています。 Listは重複を許可し、順序を持ち、Setは重複する要素を含むことができず、順序を定義しません。私はこの質問をJPAの文脈で聞いています。厳密に定義に従う場合、コレクションはリレーショナルデータベースに格納されているため、常にSetタイプを使用する必要があります。リレーショナルデータベースでは、重複がなく、自分で順序を定義できます。あなたの順序Java Listは、必ずしもDBに保存されているわけではありません。

たとえば、ほとんどの場合、List型を使用していますが、順序があるため、または重複が許可されているためではありません(とにかく所有できません)。コンポーネントライブラリの一部のコンポーネントにはリスト。

54
Theo

あなた自身の質問が示唆するように、キーはJPAではなくドメインです。 JPAは、問題に最適な方法で使用できる(そして使用する必要がある)フレームワークです。フレームワーク(またはその制限)のために次善のソリューションを選択することは、通常は警告です。

セットが必要で、順序を気にしない場合は、Setを使用します。何らかの理由で順序が重要な場合(順序付きリスト、日付順など)、List

CollectionSet、およびListの違いをよく知っているようです。どちらか一方を使用する唯一の理由は、ニーズのみに依存します。 それらを使用して、API(または将来の自己)のユーザーにコレクションのプロパティを伝える(微妙または暗黙的かもしれません)。

これは、コード全体で異なるコレクションタイプを使用する場合とまったく同じルールに従います。すべての参照にObjectまたはCollectionsを使用できますが、ほとんどの場合、より具体的な型を使用します。

たとえば、Listが表示された場合、何らかの方法でソートされていることがわかります。この場合、重複は許容されるか、無関係です。 Setが表示された場合、通常、重複や特定の順序がないことを期待します(SortedSetでない限り)。 Collectionが表示されたとき、エンティティが含まれていること以外は期待していません。

リストの順序について...はい、保存できます。そうでなくても、@OrderBy、それはまだ便利です。デフォルトでタイムスタンプでソートされたイベントログの例を考えてください。リストを人為的に並べ替えるのはあまり意味がありませんが、それでもデフォルトでソートされると便利です。

46
Konrad Garus

セットまたはリストを使用することの質問は、私が考えるよりはるかに難しいです。少なくともhibernateをJPA実装として使用する場合。リストを休止状態で使用すると、重複するCANが存在する "Bags"パラダイムに自動的に切り替わります。

そして、その決定はhibernateが実行するクエリに大きな影響を与えます。ここに小さな例があります:

2つのエンティティ、employeeおよびcompany、典型的な多対多-多くの関係。これらのエンティティを相互にマッピングするために、JoinTable(「employeeCompany」と呼びます)が存在します。

両方のエンティティ(会社/従業員)でデータタイプリストを選択します。

したがって、removeEmployeeJoefromCompanyXY、hibernateは次のクエリを実行します。

delete from employeeCompany where employeeId = Joe;
insert into employeeCompany(employeeId,companyId) values (Joe,CompanyXA);
insert into employeeCompany(employeeId,companyId) values (Joe,CompanyXB);
insert into employeeCompany(employeeId,companyId) values (Joe,CompanyXC);
insert into employeeCompany(employeeId,companyId) values (Joe,CompanyXD);
insert into employeeCompany(employeeId,companyId) values (Joe,CompanyXE);

そして今、質問:地獄はなぜそのクエリを実行するだけでなく休止状態になるのですか?

delete from employeeCompany where employeeId = Joe AND company = companyXY;

答えは簡単です(そして彼のブログ投稿でNirav Assarにたくさん感謝します):それはできません。バッグの世界では、すべてを削除して残りをすべて再挿入することが唯一の適切な方法です!より明確にするためにそれを読んでください。 http://assarconsulting.blogspot.fr/2009/08/why-hibernate-does-delete-all-then-re.html

今大きな結論:

従業員/会社-エンティティでリストではなくセットを選択した場合、その問題は発生せず、1つのクエリのみが実行されます!

そして、なぜですか?休止状態はもはやバッグの世界ではないので(ご存じのように、セットは重複を許可しません)、1つのクエリのみを実行できるようになりました。

したがって、少なくともクエリとパフォーマンスに関しては、リストとセットの決定はそれほど単純ではありません!

28
u_b

通常、リストを使用します。 List APIはSetよりもはるかに便利で、他のライブラリと互換性があると思います。リストは反復が簡単で、ほとんどの操作とメモリで一般的に効率的です。

関係に重複を持たせることはできず、通常は順序付けされていないという事実は、Setの使用を必要とするべきではありません。アプリケーションにとって最も役立つCollectionタイプを使用できます。

ただし、モデルによって異なります。多くの包含チェックを行う場合は、Setの方が効率的です。

@OrderByまたは@OrderColumnを使用して、JPAで関係を順序付けできます。

http://en.wikibooks.org/wiki/Java_Persistence/Relationships#Ordering を参照してください

JPAでは重複は通常サポートされていませんが、ElementCollectionsなどの一部のマッピングでは重複がサポートされている場合があります。

7
James

私が使う:

  • セット:コレクション内のアイテムに順序がなく、一意である場合
  • リスト:アイテムに注文がある場合
3
Ralph

Netbeansでエンティティを生成するときにコレクションを一般的なデフォルトとして使用することは良い出発点であり、モデルが実際に何であるかを理解し、より多くの機能が必要な場合、簡単に変更して下位互換性を維持できます。

0
AmanicA