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% Versuchen Sie, das Feld @ManyToOne
als faul zu markieren:
Und ändern Sie Ihre Abfrage mit einem JOIN FETCH
des account
-Feldes, um nur eine Abfrage mit allem, was Sie brauchen, zu generieren:
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:
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 ...
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):
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:
Tags und Links jpa hibernate postgresql jpql hql