JPA 2 Criteria Joinメソッドを使用すると、次のことができます。
//Join Example (default inner join)
int age = 25;
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Team> c = cb.createQuery(Team.class);
Root<Team> t = c.from(Team.class);
Join<Team, Player> p = t.join(Team_.players);
c.select(t).where(cb.equal(p.get(Player_.age), age));
TypedQuery<Team> q = entityManager.createQuery(c);
List<Team> result = q.getResultList();
Fetchメソッドを使用して同じようにするにはどうすればよいですか?Fetchインターフェイスにはパスナビゲーション用のgetメソッドがあると思っていましたが、そうではありませんでした。
//Fetch Join Example
int age = 25;
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Team> cq = cb.createQuery(Team.class);
Root<Team> t = cq.from(Team.class);
Fetch<Team,Player> p = t.fetch(Team_.players);
cq.where(cb.equal(p.get(Player_.age), age)); //This leads to compilation error there is no such method get in interface Fetch
TypedQuery<Team> q = entityManager.createQuery(cq);
List<Team> result = q.getResultList();
Hiberanteドキュメンテーションによると、fetchは間違ったJoinオブジェクトを返します。 http://docs.jboss.org/hibernate/stable/entitymanager/reference/en/html/querycriteria.html#querycriteria-from-fetch
その方法、およびあなたが言うことを許可することが期待されるという事実についてあなたに同意します。別のオプションは
_Join<Team, Player> p = t.join(Team_.players);
t.fetch(Team_.players);
c.select(t).where(cb.equal(p.get(Player_.age), age));
_
つまり、join()
を実行し、fetch()
を追加して、結合を利用します。これは非論理的であり、JPA基準の洗練されていない性質を追加するだけですが、とにかく回避策であるべきです
これは、Hibernateプロバイダーを使用して動作します。
//Join Example (default inner join)
int age = 25;
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Team> c = cb.createQuery(Team.class);
Root<Team> t = c.from(Team.class);
// Join<Team, Player> p = t.join(Team_.players);
Join<Team, Player> p = (Join<Team, Player>)t.fetch(Team_.players);
c.select(t).where(cb.equal(p.get(Player_.age), age));
TypedQuery<Team> q = entityManager.createQuery(c);
List<Team> result = q.getResultList();
確かに、移植性を損なう可能性がありますが、私たちの場合、他のhibernateの専用機能を使用しています。
* Hibernateのドキュメントにはこの例が示されていないため、非常に奇妙です。
把握するには、このインターフェースをご覧ください。
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.ejb.criteria;
import javax.persistence.criteria.Fetch;
import javax.persistence.criteria.Join;
/**
* Consolidates the {@link Join} and {@link Fetch} hierarchies since that is how we implement them.
* This allows us to treat them polymorphically.
*
* @author Steve Ebersole
*/
public interface JoinImplementor<Z,X> extends Join<Z,X>, Fetch<Z,X>, FromImplementor<Z,X> {
/**
* {@inheritDoc}
* <p/>
* Refined return type
*/
public JoinImplementor<Z,X> correlateTo(CriteriaSubqueryImpl subquery);
}
あなたがしなければならないすべては次のとおりです:
1-フェッチを行います。 2-次に、目的の場所へのパスを移動します。
あなたの場合:
int age = 25;
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Team> cq = cb.createQuery(Team.class);
Root<Team> t = cq.from(Team.class);
Fetch<Team,Player> p = t.fetch(Team_.players);
cq.where(cb.equal(t.get("player").get("age"), age));
JPA 2.1以降、動的エンティティグラフは、fetch()の代わりにjoin()を使用しながら、条件クエリでのフェッチに使用できます。質問の例から:
//Join Example (default inner join)
int age = 25;
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Team> c = cb.createQuery(Team.class);
Root<Team> t = c.from(Team.class);
Join<Team, Player> p = t.join(Team_.players);
c.select(t).where(cb.equal(p.get(Player_.age), age));
TypedQuery<Team> q = entityManager.createQuery(c);
List<Team> result = q.getResultList();
この場合:
TypedQuery<Team> q = entityManager.createQuery(c);
これに置き換えられます:
EntityGraph<Team> fetchGraph = getEntityManager().createEntityGraph(Team.class);
fetchGraph.addSubgraph(Team_.players);
TypedQuery<Team> q = entityManager.createQuery(c).setHint("javax.persistence.loadgraph", fetchGraph);
その後、すべてのプレーヤーが熱心にフェッチされます。
JPA 2.1とHibernate 4.3.7を使用していますが、以下の方法でうまくいきます。醜くも見えません。
Join<Team,Player> p = (Join) t.fetch(Team_.players);
醜いが:
Join<Team, Player> p=t.fetch(Team_.players);
sQLでフェッチを使用してsingel joinを生成しますが、JBoss6.1 hibernateで機能する醜いハックです