2012-04-12 17 views
3

私は以下のエンティティを持っています:イベントと属性。イベントは多くの属性を持つことができます。JPAが1対多にフェッチする

私が抱えている問題は、単一のSQLクエリでその属性を持つイベントを返すクエリが見つからないようです。私は反復する必要がある何百万ものイベントを持つことができ、明らかなパフォーマンス上の理由からそれらをすべてロードするのは怠惰ではありません。

私はクエリでフェッチを使用しようとしましたが、すべての属性に対してイベントを返します。すなわち、イベントが2つの属性を有する場合、各々が1つの属性を有する2つのイベントを返す。

私が欲しいのは、2つの属性を持つ1つのイベントです。

SELECT e FROM Event e LEFT JOIN FETCH e.attributes 

DISTINCTを追加すると機能しますが、大きなデータセットに対して非常に遅い別個のSQLクエリが作成されます。

public class Event { 
    @OneToMany(mappedBy = "event", cascade = CascadeType.ALL, fetch = FetchType.LAZY) 
    public Set<Attribute> getAttributes(){} 
} 

public class Attribute { 
    @ManyToOne(cascade=CascadeType.ALL) 
    @JoinColumn(name = "event_id", nullable = false) 
    public Event getEvent() { 
     return event; 
    } 
} 

ソリューション

私はJPAの解決策を見つけることができませんでした。代わりに、EntityManagerをHibernateセッションにラップし、@milkplusvellocetが示唆しているように条件の結果トランスを使用しました。これにより、個別のSQLクエリを作成せずに別個のルートエンティティを取得します。

Session session = em.unwrap(Session.class); 
Criteria criteria = session.createCriteria(Event.class); 
criteria.setFetchMode("attributes", FetchMode.JOIN); 

criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY); 

ラップされていないセッションからHQLを使用して試したことがあります。私はクエリにDISTINCTを追加し、結果のトランスフォーマをDISTINCT_ROOT_ENTITYに上記の基準ソリューションと同様に設定しました。このようにすると、はまだという別個のSQLクエリを作成しました。

答えて

3

ResultTransformerが必要です。

には、以下のHQLを試してみてください。

SELECT DISTINCT e FROM Event e LEFT JOIN FETCH e.attributes 

これは、基準クエリでCriteriaSpecification.DISTINCT_ROOT_ENTITYを使用するのと同じです。

+0

DISTINCTを追加すると、非常に遅い(distinct event0_.id as select ...)独自のSQLクエリが作成されます。 Distinctは結果全体にありますが、これはすでに異なっていますが、チェックは遅いです... JPAを使用してResultTransformerにアクセスするオプションはありません。 – kevingallagher

+0

私を正しい方向に向けてくれてありがとう。 – kevingallagher

+0

あなたはこれを解決しましたか? 'DistinctRootEntityResultTransformer'を初期化し、HQLの結果を' transformList(List) 'メソッドに渡してみてください。 – darrengorman

関連する問題