запрос указанной выборки соединения, но владелец выбранной ассоциации не присутствует в списке выбора

83

Я выбираю два столбца идентификаторов, но получаю указанную ошибку:

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]

Некоторый код:

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

Как исправить ошибку и что я делаю не так?

Вячеслав
источник
6
для будущих искателей этого вопроса в моей ситуации я присоединялся к неленивому атрибуту. Когда я удаляю пункт о присоединении, он был решен.
merveotesi
2
Я думаю, что в вашем случае проблема в том, что вы выбираете не весь объект (EntityChange), а только несколько столбцов. Предложение Fetch имеет смысл только в том случае, если выбрана корневая сущность и вы хотите, чтобы сопоставленная коллекция / объект заполнялась путем присоединения к ней.
Энди

Ответы:

117

Используйте обычный joinвместо join fetch(кстати, innerпо умолчанию):

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

Как сообщается в сообщении об ошибке, join fetchздесь нет смысла, потому что это указание на производительность, которое вызывает активную загрузку коллекции.

axtavt
источник
4
Чтобы уточнить, join fetchможет также использоваться для принудительной загрузки ассоциации, такой как поле с аннотацией @ManyToOne, а не только коллекции.
Роберт Хант,
53
Хм .. У меня аналогичная проблема, но мне нужно выполнить объединение, чтобы избежать проблемы n + 1
Женя
4
@levgen, я не знаю деталей вашего запроса, но имейте в виду, что в запросе count вообще не должно быть "выборки". codingexplained.com/coding/java/spring-framework/…
улыбка
4
@levgen Трудно помочь вам, не видя кода, но если случится так, что вы используете Spring Data с @Queryаннотацией, вы можете указать отдельные запросы для выборки и подсчета: см. этот вопрос (Spring-Data FETCH JOIN with Paging не работает) для подробностей.
naXa
2
Удаление "выборки" привело меня к проблеме N + 1, и все в моем приложении зависло. Никому не рекомендую это решение.
Алкис Мавридис
20

Поскольку вам нужна объединенная выборка, ее удаление вам не понадобится.

Вместо этого вам следует указать вместе с ним запрос количества.

Предполагая, что вы разбиваете результат на страницы, ниже приведен запрос jpa, который принимает идентификатор в качестве параметра и вызовет указанную вами проблему, а второй запрос решает это, добавляя к нему запрос count.

Примечание: fk_fieldэто атрибут в таблице А, который имеет значение «один ко многим». Запрос количества не использует сборку соединений.

@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")
мой ключ
источник