JPA 2 标准获取路径导航

问题描述 投票:0回答:8

使用 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 Documentation fetch 返回一个错误的 Join 对象。 http://docs.jboss.org/hibernate/stable/entitymanager/reference/en/html/querycriteria.html#querycriteria-from-fetch

java jpa jpa-2.0 fetch
8个回答
24
投票

同意您关于该方法的看法,以及您希望它允许您所说的事实。另一种选择是

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 Criteria 的不优雅本质,但无论如何,应该是一个解决方法


11
投票

它适用于我使用 Hibernate Provider。

//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);
}

6
投票

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

//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);

那么所有玩家都会跃跃欲试。


5
投票

您所要做的就是以下几点:

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)); 

3
投票

我正在使用 JPA 2.1 和 Hibernate 4.3.7,下面的内容对我来说效果很好。它甚至看起来也没有那么难看。

Join<Team,Player> p = (Join) t.fetch(Team_.players);

1
投票

丑陋但是:

Join<Team, Player> p=t.fetch(Team_.players);

将在 sql 中使用 fetch 生成 single join 但这是一个丑陋的黑客,可以工作 JBoss6.1 hibernate


0
投票

我将 Hibernate 版本更新为“5.6.5.Final”,我认为问题已解决。


0
投票

我从来没有想出如何帮助我的 IntelliJ IDE 帮助我处理 Entity 类的下划线问题 (

Player_
)。如果有人可以向我展示一种非常有帮助的方法,但从这个问题的答案的角度来看,我使用了以下方法来使事情正常进行:

    int age = 25;
    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
    CriteriaQuery<Team> cq = cb.createQuery(Team.class);
    Root<Team> t = cq.from(Team.class);

    Fetch<Team,Player> fetch = t.fetch("players");
    Join<Team,Player> p = (Join<Team,Player>) fetch;
    cq.select(t).where(cb.equal(p.get("age"), age));
    
    TypedQuery<Team> q = entityManager.createQuery(cq);
    List<Team> result = q.getResultList();
© www.soinside.com 2019 - 2024. All rights reserved.