Abfrage angegebenes Join-Abrufen, aber der Eigentümer der abgerufenen Zuordnung war in der Auswahlliste nicht vorhanden

81

Ich wähle zwei ID-Spalten aus, erhalte jedoch den angegebenen Fehler:

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]

Etwas Code:

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

Wie behebe ich den Fehler und was mache ich falsch?

Vyacheslav
quelle
6
Für zukünftige Suchende dieser Frage schloss ich mich in meiner Situation einem nicht faulen Attribut an. Wenn ich die Beitrittsklausel entferne, wurde sie gelöst.
Merveotesi
2
Ich denke in Ihrem Fall ist das Problem, dass Sie nicht die gesamte Entität (EntityChange) auswählen, sondern nur einige Spalten. Die Abrufklausel ist nur dann sinnvoll, wenn die Stammentität ausgewählt ist und Sie möchten, dass eine zugeordnete Sammlung / Berechtigung durch Beitritt gefüllt wird.
Andy

Antworten:

116

Verwenden Sie regulär joinstatt join fetch(übrigens innerstandardmäßig):

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

Wie die Fehlermeldung zeigt, ist join fetchdies hier nicht sinnvoll, da es sich um einen Leistungshinweis handelt, der das eifrige Laden der Sammlung erzwingt.

axtavt
quelle
4
Nur zur Verdeutlichung, join fetchkann auch verwendet werden, um das eifrige Laden einer Zuordnung zu erzwingen, z. B. eines mit @ManyToOne kommentierten Felds und nicht nur von Sammlungen.
Robert Hunt
49
Hm .. Ich stehe vor einem ähnlichen Problem, aber ich muss den Join-Abruf durchführen, um ein n + 1-Problem zu vermeiden
Zhenya
4
@levgen, ich kenne keine Details Ihrer Abfrage, aber denken Sie daran, dass die Zählabfrage überhaupt kein "Abrufen" haben sollte. codingexplained.com/coding/java/spring-framework/…
Lächeln
3
@levgen Es ist schwierig, Ihnen zu helfen, ohne einen Code zu sehen. Wenn Sie jedoch Spring Data mit @QueryAnmerkungen verwenden, können Sie separate Abfragen zum Abrufen und Zählen angeben: siehe diese Frage (Spring-Data FETCH JOIN with Paging funktioniert nicht) für Details.
NaXa
2
Das Entfernen von "Abrufen" führte zu einem N + 1-Problem und führte dazu, dass alles in meiner Anwendung hängen blieb. Würde diese Lösung niemandem empfehlen.
Alkis Mavridis
18

Da Sie den Join-Abruf benötigen, entspricht das Entfernen des Abrufs nicht Ihren Anforderungen.

Stattdessen sollten Sie eine Zählabfrage zusammen mit dieser angeben.

Angenommen, Sie paginieren das Ergebnis. Im Folgenden finden Sie eine jpa-Abfrage, die id als Parameter verwendet und das von Ihnen angegebene Problem verursacht. Die zweite Abfrage löst dieses Problem, indem sie eine Zählabfrage hinzufügt.

Hinweis: fk_fieldist das Attribut in Tabelle A, das den Eins-zu-Viele-Wert hat. Die Zählabfrage verwendet keinen Join-Abruf.

@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")
mein Schlüssel
quelle