2016-04-22 6 views
3

私は@ManyToOneの関係を持つエンティティを持っています。これは、単一のクエリで検索したいので、@Fetch(FetchMode.JOIN)を使用しています。時にはHibernateはそれを尊重せず、N + 1 SELECTを発行します。 で時々私はそれが何を引き起こすのか分からないので、私は異なるクラスの同じクラスでこれが起こるかどうかを知ることができます。なぜHibernateはFetchMode.JOINを無視することがあるのですか?

これは私が使用して注釈を単純化した実体である:私は、単一のクエリは、

select ... from Employee join Department on ... 
のようなものを Employeeとその Departmentの両方を取得するために期待される

CriteriaQuery<Employee> criteriaQuery = criteriaBuilder.createQuery(Employee.class); 

Root<Employee> root = criteriqQuery.from(Employee.class); 

TypedQuery<Employee> typedQuery = entityManager.createQuery(criteriaQuery); 

List<Employee> employees = typedQuery.getResultList(); 

@Entity 
public class Employee { 

    @ManyToOne 
    @Fetch(FetchMode.JOIN) 
    private Department department; 

} 

代わりに、最初にすべてを選択しますN Employee秒、次にN SELECT秒、Department秒(キャッシュなし)。

私は多くの同様の質問を見つけましたが、その回答は回避策を示唆し、なぜこれが起こっているのか説明しません。レイジーローディングを使用することを提案する回答は避けてください。それは私が求めているものではありません。

答えて

5

ルールは非常に簡単です。クエリはフェッチモードを無視します。クエリを記述すると、結合されたものと結合されていないものを伝えます。

フェッチモードは、エンティティにEntityManager.find(class, id)のようなメソッドがロードされている場合や、他のエンティティグラフをナビゲートして関連付けをロードする場合にのみ考慮されます。

+0

ありがとうございました!つまり、Criteria APIは '@Fetch'を無視しますが、' Root.fetch() '(JPA)を使用しても同じ結果が得られます。 –

関連する問題