2016-04-12 4 views
0

私はプロジェクトのリストと顧客のリストを持っています。プロジェクトは1人の顧客のためのものであり、すべての顧客は多くのプロジェクトを持つことができます。したがって、プロジェクトが所有側であるシンプルな1:nの関係です。不可欠に簡素化された これはN + 1の問題ですか?どのように修正するのですか?

それは私がプロジェクトのリストをロードすると、私は同じ時間で効率的に顧客を取得したい

@Entity 
public class Project { 
    @Id 
    long id; 

    @ManyToOne(optional = true) 
    @JoinColumn(name = "customer", nullable = true, updatable = true) 
    Customer customer; 
} 

@Entity 
public class Customer { 
    @Id 
    long id; 
} 

です。これはそうではありません。プロジェクトのための1つのクエリがあり、それから別個のクエリが発行されるすべての個別の顧客のためです。

だから私は50の異なる顧客に割り当てられている100のプロジェクトがあると言います。これにより、プロジェクトのクエリーが1つ、顧客のクエリーが50件になります。

これはすぐに大きなプロジェクト/顧客リストを追加し、私たちのアプリケーションはかなり遅くなります。これは単なる一例です。関係を持つすべてのエンティティは、この動作の影響を受けます。

示唆したように、私はすでにherecustomersフィールド上@Fetch(FetchMode.JOIN)を試みたが、それは何もしてFetchMode.SUBQUERYしませんが休止状態に応じて適用されない:

org.hibernate.AnnotationException:FetchMode.SUBSELECTの使用はトゥーン団体に許可されていません

この問題を解決するにはどうすればよいですか?

+0

私はそれはN + 1問題だとは思わない、デフォルトのフェッチ・タイプあなたのために'@ ManyToOne'の関係はすでに' FetchType.EAGER'です –

答えて

1

はい、これはn + 1選択問題のバイブルの例です。

私がほとんどの場合に使用するアプローチは、アソシエーションを遅延させ、batch sizeを定義することです。

代わりに、クエリの結果セットから直接の関連付けを初期化するために[left] join fetchとJPQLクエリを使用することができます。

select p from Project p left join fetch p.customer 
+0

それは唯一の方法ですか?私はSpring Dataを使用しており、必ずしも書面による照会を必要としないので、私は尋ねています。 '@Fetch(FetchMode.JOIN)'は同じことをしてはいけませんか? – musiKk

+0

'FetchMode'はクエリに影響を与えません(Springデータはおそらくリポジトリメソッドの命名規則に基づいて自動的に自動生成されます)。 PS Spring Dataでは、クエリの作成を妨げません。 –

+0

これは当てはまりますが、afaikがクエリを書くことを許可しない 'JpaSpecificationExecutor'インタフェースを使用しています。 [私は仕様でフェッチモードを設定することができます](https://jdpgrailsdev.github.io/blog/2014/09/09/spring_data_hibernate_join.html)しかし、それは私には非常にハッキーに見えます。私は基本的に仕様の副作用に頼って、自分が望むものを達成する必要があります。 – musiKk

関連する問題