Cómo obtener todos los datos en una consulta

Tengo varias entidades que se consultan a través de JPA2 Criterios de Consulta.

Soy capaz de unir dos de estas entidades y obtener el resultado a la vez:

CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<LadungRgvorschlag> criteriaQuery = criteriaBuilder.createQuery(LadungRgvorschlag.class);
Root<LadungRgvorschlag> from = criteriaQuery.from(LadungRgvorschlag.class);
Join<Object, Object> ladung = from.join("ladung");

from.fetch("ladung", JoinType.INNER);

Entonces yo trate de unirse a una tabla adicional como que:

ladung.join("ladBerechnet");
ladung.fetch("ladBerechnet", JoinType.LEFT);

me sale el siguiente error:

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=generatedAlias3,role=null,tableName=ladberechnet,tableAlias=ladberechn3_,origin=ladungen ladung1_,columns={ladung1_.id ,className=de.schuechen.beans.tms.master.LadBerechnet}}] [select generatedAlias0 from de.schuechen.beans.tms.master.LadungRgvorschlag as generatedAlias0 inner join generatedAlias0.ladung as generatedAlias1 inner join generatedAlias1.ladBerechnet as generatedAlias2 left join fetch generatedAlias1.ladBerechnet as generatedAlias3 inner join fetch generatedAlias0.ladung as generatedAlias4 where ( generatedAlias0.erledigt is null ) and ( generatedAlias0.belegart in (:param0, :param1) ) and ( generatedAlias1.fzadresse in (:param2, :param3) ) and ( generatedAlias1.zudatum<=:param4 ) and ( 1=1 ) order by generatedAlias0.belegart asc, generatedAlias1.fzadresse asc, generatedAlias1.zudatum asc, generatedAlias1.zulkw asc]

¿Cómo puedo saber JPA/Hibernate, que se deben seleccionar todas las entidades que a la vez?

OriginalEl autor Stinnux | 2011-12-15

2 Kommentare

  1. 11

    Con JPA ‘algunos dialectos de JPA’ usted puede unirse a la cadena de recuperaciones, pero creo que no se puede/debe hacer tanto una combinación y un join fetch.

    Por ejemplo, si tenemos un Program que tiene una relación de uno a muchos relación a un Reward que tiene una relación con un Duration, los siguientes JPQL obtendría una instancia específica con las recompensas y la duración precargadas:

    SELECT DISTINCT
        program
    FROM
        Program _program
            LEFT JOIN FETCH
        _program.rewards _reward
            LEFT JOIN FETCH
        _reward.duration _duration
    WHERE
        _program.id = :programId
    
    }

    Con los Criterios equivalentes código:

    CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
    CriteriaQuery<Program> criteriaQuery = criteriaBuilder.createQuery(Program.class);
    Root<Program> root = criteriaQuery.from(Program.class);
    
    Fetch<Program, Reward> reward = root.fetch("rewards", JoinType.LEFT);
    Fetch<Reward, Duration> duration = reward.fetch("duration", JoinType.LEFT);
    
    criteriaQuery.where(criteriaBuilder.equal(root.get("id"), programId));
    
    TypedQuery<program> query = entityManager.createQuery(criteriaQuery);
    
    return query.getSingleResult();

    Tenga en cuenta que las variables intermedias de la recompensa y la duración no son necesarios aquí, pero son sólo para fines informativos. root.fetch("rewards", JoinType.LEFT).fetch("duration", JoinType.LEFT) tendría el mismo efecto.

    Funciona porque de extensiones de fabricantes en algunas implementaciones (como Hibernate, por ejemplo). En JPA, en general, esta consulta JPQL no funciona, porque el encadenamiento de los alias y en este caso no son necesarios para ser admitidos de acuerdo a la especificación.
    Gracias por la aclaración Mikko. Es bastante desagradable que dichas extensiones están en silencio activado, por lo que el uso de ellos sin realmente darse cuenta de ello.
    si es un proveedor de extensión, entonces ¿por qué los Criterios de la API devuelve un Fetch instancia en la que podemos llamar fetch() de nuevo?
    Por desgracia, yo no sé acerca de la motivación detrás de estas decisiones de diseño. Tal vez prefieren la simplicidad de la interfaz de más de precisión.
    Tal vez incluso funciona, las cosas es que si funciona, funciona debido a la persistencia de proveedor extensiones de funcionalidad. Proporcionar implementaciones de muchas otras cosas útiles, lo cual es bueno, al menos mientras no hay necesidad de cambiar de aplicación.

    OriginalEl autor Arjan Tijms

  2. 7

    Lo que se trata de la app, usted no puede unirse a la cadena de capturas en los Criterios de la API de consultas (cita de la especificación):

    Una asociación o un atributo que hace referencia el método de búsqueda debe ser
    hace referencia a una entidad o incrustable que se devuelve como resultado
    de la consulta. Una captura combinación tiene la misma unirse a la semántica como la
    correspondientes interior o el exterior de la combinación, excepto que los objetos relacionados
    no objetos de nivel superior en el resultado de la consulta y no se puede hacer referencia
    en otra parte por la consulta.

    Y tampoco se admite en las consultas JPQL:

    La asociación que se hace referencia por el lado derecho de la cláusula JOIN FETCH
    debe ser una asociación o elemento de la colección que se hace referencia en
    una entidad o incrustable que se devuelve como resultado de la consulta.

    No se permite especificar una variable para la identificación de
    los objetos referenciados por el lado derecho de la cláusula JOIN FETCH, y
    de ahí las referencias al implícitamente recuperan las entidades o elementos no
    aparecen en otros lugares de la consulta.

    Con HQL parece ser posible: La documentación de Hibernate EclipseLink no proporciona una extensión, por lo que la sintaxis de la consulta siguiente es aceptado por Hibernate, pero no por EclipseLink:

    SELECT a FROM A a LEFT JOIN FETCH a.bb b LEFT JOIN FETCH b.cc

    En EclipseLink mismo se puede hacer a través de sugerencias de consulta.

    OriginalEl autor Mikko Maunu

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea