JPA 2条件获取路径导航

使用JPA 2 Criteria Join方法,我可以执行以下操作:

//Join Example (default inner join) int age = 25; CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery c = cb.createQuery(Team.class); Root t = c.from(Team.class); Join p = t.join(Team_.players); c.select(t).where(cb.equal(p.get(Player_.age), age)); TypedQuery q = entityManager.createQuery(c); List result = q.getResultList(); 

我怎么能用fetch方法做同样的事情,我期望Fetch接口有get路径导航方法,但它没有:

  //Fetch Join Example int age = 25; CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery cq = cb.createQuery(Team.class); Root t = cq.from(Team.class); Fetch 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 q = entityManager.createQuery(cq); List result = q.getResultList(); 

根据Hiberante Documentation fetch返回一个错误的Join对象。 http://docs.jboss.org/hibernate/stable/entitymanager/reference/en/html/querycriteria.html#querycriteria-from-fetch

同意你对这种方法的看法,以及你希望它允许你所说的这一事实。 另一种选择是

 Join p = t.join(Team_.players); t.fetch(Team_.players); c.select(t).where(cb.equal(p.get(Player_.age), age)); 

即,执行join() ,为它添加一个fetch() ,然后使用join。 这是不合逻辑的,只会增加JPA标准的不雅性,但无论如何,应该是一个变通方法

它适用于我使用Hibernate Provider。

 //Join Example (default inner join) int age = 25; CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery c = cb.createQuery(Team.class); Root t = c.from(Team.class); // Join p = t.join(Team_.players); Join p = (Join)t.fetch(Team_.players); c.select(t).where(cb.equal(p.get(Player_.age), age)); TypedQuery q = entityManager.createQuery(c); List result = q.getResultList(); 

当然,它可能会破坏可移植性,但在我们的例子中,我们一直在使用其他hibernate的独有function。

*这很奇怪,因为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 extends Join, Fetch, FromImplementor { /** * {@inheritDoc} * 

* Refined return type */ public JoinImplementor correlateTo(CriteriaSubqueryImpl subquery); }

您所要做的就是以下内容:

1-取得。 2-然后,走过你想要的路径。

在你的情况下:

 int age = 25; CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery cq = cb.createQuery(Team.class); Root t = cq.from(Team.class); Fetch p = t.fetch(Team_.players); cq.where(cb.equal(t.get("player").get("age"), age)); 

从JPA 2.1开始,动态实体图可用于在条件查询中获取,同时使用join()而不是fetch()。 从问题中的示例:

 //Join Example (default inner join) int age = 25; CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery c = cb.createQuery(Team.class); Root t = c.from(Team.class); Join p = t.join(Team_.players); c.select(t).where(cb.equal(p.get(Player_.age), age)); TypedQuery q = entityManager.createQuery(c); List result = q.getResultList(); 

如果这:

 TypedQuery q = entityManager.createQuery(c); 

被替换为:

 EntityGraph fetchGraph = getEntityManager().createEntityGraph(Team.class); fetchGraph.addSubgraph(Team_.players); TypedQuery q = entityManager.createQuery(c).setHint("javax.persistence.loadgraph", fetchGraph); 

然后所有球员都会渴望获得。

我正在使用JPA 2.1与Hibernate 4.3.7,以下对我很有用。 它甚至看起来都不那么难看。

 Join p = (Join) t.fetch(Team_.players); 

丑陋但是:

 Join p=t.fetch(Team_.players); 

将在sql中使用fetch生成singel连接,但这是一个丑陋的hack,它运行JBoss6.1 hibernate