Verringern Sie die Anzahl der Abfragen für JPQL POJO, die eine Entität enthalten

8

Entitätsbeziehung: Transaktion (@ManyToOne - standardmäßig begierig) - & gt; Konto

%Vor%

Standardmäßig generiert JPA mit der Hibernate-Implementierung 1 + n Abfragen. Die n Abfragen dienen zum verzögerten Laden der Account-Entitäten.

Wie kann ich diese Abfrage eifrig machen und alles mit einer einzigen Abfrage laden? Das SQL-Äquivalent wäre etwas wie

%Vor%

, eine Syntax, die gut auf PostgreSQL funktioniert. Aus meinen Ergebnissen generiert Hibernate eine Abfrage, die das verzögerte Laden rechtfertigt.

%Vor%     
danidacar 06.10.2016, 07:05
quelle

3 Antworten

4

Versuchen Sie, das Feld @ManyToOne als faul zu markieren:

%Vor%

Und ändern Sie Ihre Abfrage mit einem JOIN FETCH des account -Feldes, um nur eine Abfrage mit allem, was Sie brauchen, zu generieren:

%Vor%

UPDATE:

Entschuldigung, Sie haben Recht, das Attribut fetch von @ManyToOne ist nicht erforderlich, da dies im Hibernate der Standardwert ist. % Co_de% funktioniert nicht, es verursacht JOIN FETCH : "Abgefragten Join-Abruf abfragen, aber der Besitzer der abgerufenen Assoziation war nicht vorhanden".

Ich habe versucht mit einigen anderen Ansätzen, die einfachste, die n + 1 Abfragen zu vermeiden ist, ist die Erstellung des QueryException -Objekts aus Ihrer Abfrage zu entfernen und die Ergebnisliste zu verarbeiten, indem Sie die Objekte manuell erstellen:

%Vor%     
JMSilla 06.10.2016 10:14
quelle
2

Nun wird PostgreSQL (und auch jede andere SQL-Datenbank) Sie davon abhalten, die erwähnte Abfrage zu verwenden: Sie müssen nach allen Spalten der Kontentabelle gruppieren, nicht nach der ID. Aus diesem Grund generiert Hibernate die Abfrage, Gruppierung nach ID des Accounts - das ist, was beabsichtigt ist, und dann holen Sie die anderen Teile. Da es im Allgemeinen nicht vorhersagen kann, was noch benötigt wird, um verbunden und gruppiert zu werden (!!!), kann dies im Allgemeinen Situation erzeugen, wenn mehrere Entitäten mit der gleichen ID abgerufen werden (erstellen Sie einfach eine richtige Abfrage und nehmen Sie eine Schauen Sie sich den Ausführungsplan an, dies ist besonders wichtig, wenn Sie OneToMany -Felder in Ihrer Account -Entität oder einem anderen ManyToOne -Teil der Account -Entity haben), deshalb verhält sich Hibernate auf diese Weise.

Wenn Sie Accounts mit den angegebenen IDs im First-Level-Cache haben, erzwingt Hibernate, sie von dort abzuholen. Oder, wenn sie selten modifizierte Entitäten sind, können Sie sie in den Second-Level-Cache stellen, und Hibernate wird keine Datenbankabfrage durchführen, sondern sie aus dem Second-Level-Cache holen.

Wenn Sie diese aus der Datenbank in einem einzelnen Hinweis abrufen müssen, aber nicht die ganze Funktionalität von Hibernate verwenden möchten, gehen Sie einfach zum reinen JPA-Ansatz basierend auf nativen Abfragen wie folgt vor:

%Vor%

Sicherlich wird dies für Sie gut funktionieren, wenn Sie nicht das Konto verwenden, das von dieser Abfrage in anderen Entitäten abgerufen wird . Dadurch wird Hibernate "verrückt" - die "Entität", aber nicht von Hibernate abgerufen ...

    
Ilya Dyoshin 16.10.2016 08:22
quelle
1

Interessant, das beschriebene Verhalten ist so, als würden t instances von der tatsächlichen Abfrage zurückgegeben und t.account association im ersten Argument von Pojo constructor wird tatsächlich in t -Instanzen beim Marshalling von Ergebnissen der Abfrage navigiert ( beim Erstellen von Pojo -Instanzen aus den Ergebniszeilen der Abfrage). Ich bin mir nicht sicher, ob dies ein Fehler oder eine beabsichtigte Funktion für Konstruktorausdrücke ist.

Aber die folgende Form der Abfrage sollte funktionieren (keine t.account Navigation im Konstruktorausdruck und keine join fetch ohne den Besitzer der abgerufenen Assoziation, weil es keinen Sinn ergibt, etwas eifrig zu initialisieren, das nicht wirklich zurückgegeben wird aus der Abfrage):

%Vor%

BEARBEITEN

Sehr gute Beobachtung von Ilya Dyoshin über die group by -Klausel; Ich habe es hier komplett überwacht. Um in der HQL-Welt zu bleiben, könnten Sie einfach alle Konten mit Transaktionen vorladen, bevor Sie die Abfrage mit Gruppierung ausführen:

%Vor%     
Dragan Bozanovic 12.10.2016 20:27
quelle

Tags und Links