búsqueda de unión especificada de consulta, pero el propietario de la asociación obtenida no estaba presente en la lista de selección

82

Estoy seleccionando dos columnas de identificación pero obtengo el error especificado:

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=r,role=null,tableName=REVISIONS,tableAlias=revision1_,origin=ENTITY_CHANGED_IN_REVISION entitychan0_,columns={entitychan0_.REV_ID ,className=ru.csbi.registry.domain.envers.Revision}}] [ select ec.id as entityChangeId, r.id as revisionId from ru.csbi.registry.domain.envers.EntityChange as ec  inner join fetch ec.revision as r  where ec.groupEntityId = :groupEntityId and ec.groupName = :groupName  and r.timestamp < :entityDateFrom  and r.timestamp > :entityDateTo  and (        ec.revisionType in (0, 5, 1, 4, 2 )       and not ( ec.otherGroupEntityModified = false and ec.thisGroupEntityModified = true and ec.rowDataModified = false and ec.collectionOfNotGroupEntityModified = false   )      )  group by ec.id, r.id  having count(*) > :start order by r.id desc]

Algún código:

String hql = " select ec.id as entityChangeId, r.id as revisionId from EntityChange as ec " +
            " inner join fetch ec.revision as r " +
            " where ec.groupEntityId = :groupEntityId" +
            " and ec.groupName = :groupName " +
            " and r.timestamp < :entityDateFrom " +
            " and r.timestamp > :entityDateTo " +
            " and ( " +
            "       ec.revisionType in (" + 
                        RevisionType.ADD.getRepresentation() + ", " + 
                        RevisionType.ONLY_DATA_PROPERTY_MOD.getRepresentation() + ", " +
                        RevisionType.BOTH_COLLECTION_AND_PROPERTY_MOD.getRepresentation() + ", " +
                        RevisionType.ONLY_COLLECTION_PROPERTY_MOD.getRepresentation() + ", " +
                        RevisionType.DEL.getRepresentation() +
                    " ) " +
            "     and not ( "+
                    "ec.otherGroupEntityModified = false and " +
                    "ec.thisGroupEntityModified = true and " +
                    "ec.rowDataModified = false and " +
                    "ec.collectionOfNotGroupEntityModified = false " +
                "  ) " +
            "     ) " +
            " group by ec.id, r.id " +
            " having count(*) > :start" +
            " order by r.id desc";

¿Cómo corregir el error y qué estoy haciendo mal?

Vyacheslav
fuente
6
para futuros buscadores de esta pregunta, en mi situación, me unía a un atributo no perezoso. Cuando elimino la cláusula de unión, se resolvió.
merveotesi
2
Creo que en su caso, el problema es que no selecciona toda la entidad (EntityChange) sino solo unas pocas columnas. La cláusula Fetch solo tiene sentido si se selecciona la entidad raíz y desea que se complete una colección / entidad mapeada al unirse a ella.
Andy

Respuestas:

116

Use regular en joinlugar de join fetch(por cierto, es innerpor defecto):

String hql = " select ec.id as entityChangeId, r.id as revisionId from EntityChange as ec " + 
        " join ec.revision as r " + ...

Como le dice el mensaje de error, join fetchno tiene sentido aquí, porque es una pista de rendimiento que fuerza la carga ansiosa de la colección.

axtavt
fuente
4
Solo para aclarar, join fetchtambién se puede usar para forzar la carga ansiosa de una asociación, como un campo anotado con @ManyToOne y no solo colecciones.
Robert Hunt
49
Hm ... Estoy enfrentando un problema similar, pero necesito hacer la búsqueda de combinación para evitar el problema n + 1
Zhenya
4
@levgen, no conozco los detalles de su consulta, pero tenga en cuenta que la consulta de recuento no debe tener "recuperación" en absoluto. codingexplained.com/coding/java/spring-framework/…
smile
3
@levgen Es difícil ayudarlo sin ver un código, pero si sucede que usa Spring Data con @Queryanotación, entonces puede especificar consultas separadas para obtener y contar: vea esta pregunta (Spring-Data FETCH JOIN with Paging no funciona) para detalles.
naXa
2
Eliminar "buscar" me llevó al problema N + 1 y provocó que todo en mi aplicación se bloqueara. No recomendaría esta solución a nadie.
Alkis Mavridis
18

Como necesita la recuperación de unión, eliminar la recuperación no satisfará sus necesidades.

Lo que debería hacer en su lugar es especificar una consulta de recuento junto con ella.

Suponiendo que está paginando el resultado, a continuación se muestra la consulta jpa que toma id como parámetro y causará el problema que especificó y la segunda consulta lo resuelve agregando una consulta de recuento.

Nota: fk_fieldes el atributo en la tablaA que tiene el rln de uno a muchos. La consulta de recuento no utiliza la recuperación de combinación.

@Query(value = "from TableA a LEFT JOIN FETCH a.fk_field where a.id = :id") 

@Query(value = "from TableA a LEFT JOIN FETCH a.fk_field where a.id = :id", 
  countQuery = " select  count(a) from TableA a left join a.fk_field where a.id = :id")
mi llave
fuente