JPA 2 Criterios Buscar Ruta de Navegación


Con el método JPA 2 Criteria Join puedo hacer lo siguiente:

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

¿Cómo puedo hacer lo mismo con el método fetch, esperaba que la interfaz Fetch tuviera el método get para la navegación de rutas, pero no es así:

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

De acuerdo con la documentación de Hiberante, fetch devuelve un objeto Join que es incorrecto. http://docs.jboss.org/hibernate/stable/entitymanager/reference/en/html/querycriteria.html#querycriteria-from-fetch

Author: Alfredo Osorio, 2010-12-22

6 answers

Estoy de acuerdo contigo sobre ese método, y el hecho de que esperarías que permitiera lo que dices. Otra opción sería

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

Es decir, hacer un join(), añadir un fetch() para él, y luego hacer uso de la combinación. Esto es ilógico y solo se suma a la naturaleza poco elegante de los criterios de JPA, pero de todos modos, debería ser una solución

 19
Author: DataNucleus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-19 09:23:51

Funciona para mí usando 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();

Ciertamente, podría romper la portabilidad, pero en nuestro caso hemos estado usando otras características exclusivas de hibernate.

*Es muy extraño porque la documentación de hibernación no muestra este ejemplo.

Para entenderlo mira esta interfaz.

/*
 * 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);
}
 9
Author: Eduardo Fabricio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-28 14:16:47

Todo lo que tienes que hacer es lo siguiente:

1 - Hacer Fetch. 2-Luego, recorre el camino hacia donde quieras.

En su caso:

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)); 
 4
Author: Haytham Salhi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-15 22:06:57

Comenzando con JPA 2.1, se pueden usar gráficos de entidades dinámicas para obtener consultas de criterios, mientras se usa join() en lugar de fetch(). Del ejemplo en la pregunta:

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

Si esto:

TypedQuery<Team> q = entityManager.createQuery(c);

Se sustituye por esto:

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

Entonces todos los jugadores serán buscados ansiosos.

 3
Author: Darren Reimer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-23 18:21:33

Estoy usando JPA 2.1 con Hibernate 4.3.7 y lo siguiente me funciona bien. Ni siquiera se ve tan feo.

Join<Team,Player> p = (Join) t.fetch(Team_.players);
 1
Author: thegeko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-11 18:42:33

Feo pero:

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

Producirá singel join con fetch en sql pero es un truco feo que funciona JBoss6.1 hibernar

 0
Author: Jernej,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-26 23:02:44