251

通常の JOIN を使用する場所と JOIN FETCH を使用する場所を理解するのを手伝ってください。たとえば、次の 2 つのクエリがあるとします。

FROM Employee emp
JOIN emp.department dep

FROM Employee emp
JOIN FETCH emp.department dep

それらの間に違いはありますか?はいの場合、いつどちらを使用しますか?

4

5 に答える 5

251

この 2 つのクエリでは、JOIN を使用して、少なくとも 1 つの部門が関連付けられているすべての従業員をクエリしています。

ただし、違いは次のとおりです。最初のクエリでは、Hibernate の従業員のみが返されます。2 番目のクエリでは、Employeesと関連するすべての部門を返します。

したがって、2 番目のクエリを使用する場合、各従業員の部門を表示するためにデータベースに再度アクセスするために新しいクエリを実行する必要はありません。

各従業員の部門が必要であることが確実な場合は、2 番目のクエリを使用できます。Department が必要ない場合は、最初のクエリを使用します。

いくつかの WHERE 条件を適用する必要がある場合は、このリンクを読むことをお勧めします (おそらく必要になるもの): JPA 2 CriteriaQuery として "where" 句を使用して JPQL "join fetch" を適切に表現する方法?

アップデート

使用せずfetchに Departments が返され続ける場合は、Employee と Department (a @OneToMany)の間のマッピングが で設定されているためFetchType.EAGERです。この場合、どの HQL (withfetchまたは not) クエリでFROM Employeeも、すべての部門が取得されます。すべてのマッピング *ToOne (@ManyToOneおよび@OneToOne) はデフォルトで EAGER であることに注意してください。

于 2014-04-30T00:37:15.453 に答える
77

コメントで前に述べたこのリンクで、この部分を読んでください

「フェッチ」結合を使用すると、値の関連付けまたはコレクションを、単一の選択を使用して親オブジェクトとともに初期化できます。これは、コレクションの場合に特に役立ちます。アソシエーションとコレクションのマッピング ファイルの外部結合と遅延宣言を効果的にオーバーライドします。

この「JOIN FETCH」は、エンティティ内のコレクションの (fetch = FetchType.LAZY) プロパティを持っている場合に効果があります (以下の例)。

そして、それは「クエリがいつ発生するか」というメソッドにのみ影響します。また、次のことも知っておく必要があります

hibernate には 2 つの直交する概念があります。関連付けがフェッチされるタイミングとフェッチされる方法です。それらを混同しないことが重要です。fetch を使用してパフォーマンスを調整します。lazy を使用して、特定のクラスのデタッチされたインスタンスで常に利用できるデータの契約を定義できます。

関連付けが取得されるのはいつですか --> あなたの「FETCH」タイプ

どのようにフェッチされますか --> Join/select/Subselect/Batch

あなたの場合、FETCH は、従業員内に部門をセットとして持っている場合にのみ効果があります。エンティティでは次のようになります。

@OneToMany(fetch = FetchType.LAZY)
private Set<Department> department;

使用するとき

FROM Employee emp
JOIN FETCH emp.department dep

と が得られempますemp.dep。フェッチを使用しなかった場合でも取得できますemp.depが、休止状態はデータベースへの別の選択を処理して、その部門のセットを取得します。

したがって、パフォーマンスの調整の問題です。すべての結果を(必要かどうかに関係なく)単一のクエリで取得するか(イーガーフェッチ)、必要なときに後でクエリを実行するか(レイジーフェッチ)についてです。

1 つの選択 (1 つの大きなクエリ) で小さなデータを取得する必要がある場合は、熱心なフェッチを使用します。または、遅延フェッチを使用して、後で必要なものをクエリします(多くの小さなクエリ)。

次の場合にフェッチを使用します。

  • あなたが取得しようとしているエンティティ内に大きな不要なコレクション/セットはありません

  • アプリケーション サーバーからデータベース サーバーへの通信が遠すぎて、長時間かかる

  • そのコレクションにアクセスできない場合は、後でそのコレクションが必要になる場合があります(トランザクションメソッド/クラスの外部)。

于 2013-07-03T04:27:39.903 に答える
2

Dherik : あなたの言うことはよくわかりませんが、fetch を使用しない場合、結果の型は :List<Object[ ]>つまり、従業員のリストではなく、オブジェクト テーブルのリストになります。

Object[0] refers an Employee entity 
Object[1] refers a Departement entity 

fetch を使用すると、選択は 1 つだけで、結果はList<Employee>部門のリストを含む Employee のリストになります。エンティティの遅延宣言をオーバーライドします。

于 2015-02-21T18:02:06.767 に答える