2016-08-16 14 views
4

と複数選択します他の多くのプロパティがあり、私は最高のパフォーマンスを持っていたいと思います)。JPAの基準は、私がモデルを以下しているフェッチ

私が書くとき、クエリ:

Caused by: org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list [FromElement{explicit,not a collection join,fetch join,fetch non-lazy properties,classAlias=generatedAlias1,role=com.sample.SampleModel.model.SampleModel.mentor,tableName=USER_,tableAlias=user1_,origin=SampleModel SampleModel0_,columns={SampleModel0_.MENTOR_ID ,className=com.sample.credential.model.User}}] 
    at org.hibernate.hql.internal.ast.tree.SelectClause.initializeExplicitSelectClause(SelectClause.java:214) 
    at org.hibernate.hql.internal.ast.HqlSqlWalker.useSelectClause(HqlSqlWalker.java:991) 
    at org.hibernate.hql.internal.ast.HqlSqlWalker.processQuery(HqlSqlWalker.java:759) 
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:675) 
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:311) 
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:259) 
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:262) 
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:190) 
    ... 138 more 

クエリ例外の前に:私は例外次いる

CriteriaBuilder builder = em.getCriteriaBuilder(); 
CriteriaQuery<SampleModel> query = builder.createQuery(SampleModel.class); 
Root<SampleModel> root = query.from(SampleModel.class); 
query.select(root).distinct(true); 
root.fetch(SampleModel_.mentor, JoinType.LEFT); 

query.multiselect(root.get(SampleModel_.id), root.get(SampleModel_.name), root.get(SampleModel_.shortName), root.get(SampleModel_.mentor)); 
query.orderBy(builder.asc(root.get(SampleModel_.name))); 
TypedQuery<SampleModel> allQuery = em.createQuery(query); 
return allQuery.getResultList(); 

SELECT DISTINCT NEW com.sample.SampleModel.model.SampleModel(generatedAlias0.id, generatedAlias0.name, generatedAlias0.shortName, generatedAlias0.mentor) 
FROM com.sample.SampleModel.model.SampleModel AS generatedAlias0 
LEFT JOIN FETCH generatedAlias0.mentor AS generatedAlias1 
ORDER BY generatedAlias0.name ASC 

私は私が参加してフェッチ置き換えることができることを知っているが、その後私はN + 1の問題を抱えています。また、私は戻ったSampleModelへのユーザーからの参照を持っていないと私はしたくない...

答えて

1

私はこの同じ問題に走った、と私は使用してそれを回避することができたことがわかった:

CriteriaQuery<Tuple> crit = builder.createTupleQuery(); 

の代わりに

CriteriaQuery<X> crit = builder.createQuery(X.class); 

最終結果を生成するために少しの作業が必要です。あなたのケースで:

return allQuery.getResultList().stream() 
    map(tuple -> { 
     return new SampleModel(tuple.get(0, ...), ...)); 
    }) 
    .collect(toList()); 
0

私はJPAプロバイダとしてのEclipseLinkを使用して、同じ問題を抱えて:私はちょうど(Gazeciarzの例では、«ユーザー»)マッピングされたエンティティのIDを返したかったです。

これは、代わりにユーザーのすべてのフィールドを返すので、その後

root.get(SampleModel_.mentor).get(User_.id) 

ようなもので(query.multiselect句に)置き換えることにより、非常に単純にリクエストを

root.get(SampleModel_.mentor) 

を達成することができますそのidだけを返します。

私もタプルクエリを使用しましたが、私の場合は、クエリが複数のエンティティからのfiledsを返すためでした。

0

質問がありましたので、しばらくお待ちください。しかし、私は他の人が私のソリューションから恩恵を受けることを願っています:

トリックはサブクエリを使用することです。

のは、あなたのアプリケーションの実体に申請を持っていると仮定しましょう(1対1):

@Entity 
public class Application {  

    private long id; 
    private Date date; 

    @OneToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "some_id") 
    private Applicant applicant; 

    // Other fields 

    public Application() {} 

    public Application(long id, Date date, Applicant applicant) { 
     // Setters 
    } 
} 

//............... 

CriteriaBuilder cb = entityManager.getCriteriaBuilder(); 
CriteriaQuery<Application> cbQuery = cb.createQuery(Application.class); 

Root<Application> root = cbQuery.from(Application.class); 

Subquery<Applicant> subquery = cbQuery.subquery(Applicant.class); 
Root subRoot = subquery.from(Applicant.class); 

subquery.select(subRoot).where(cb.equal(root.get("applicant"), subRoot)); 
cbQuery.multiselect(root.get("id"), root.get("date"), subquery.getSelection()); 

このコードは、アプリケーションのselect文、および各アプリケーションごとの申請のためのSELECT文を生成します。

マルチセレクションに対応する適切なコンストラクタを定義する必要があることに注意してください。

関連する問題