Hibernate führt mehrere Auswahlanforderungen aus und verwendet stattdessen Join Fetch.

8

Ich habe die folgende Abfrage, die ich in einer einzelnen Select-Anfrage ausführen soll:

%Vor%

Das Problem besteht darin, dass alles durch separate Mehrfachabfragen abgerufen wird. Ich möchte nur die Team- und Teamspieler und die Fähigkeiten jedes Spielers in einer einzigen Anfrage holen. Aber stattdessen habe ich mehrere Select-Abfragen, um jedes Team, jeden Spieler, die Statistiken und Fähigkeiten jedes Spielers abzurufen.

Hier sind Entitäten, die mit Anmerkungen verwendet werden:

Spielelement:

%Vor%

Team Entity:

%Vor%

Spielereinheit:

%Vor%

Können Sie auf die Fehler hinweisen? Ich brauche eine Select-Abfrage, um das Spiel, die Teams, die Spieler des Teams und die Fähigkeiten jedes Spielers zu laden.

EDIT 1: hier ist postgresql log (ein Teil davon), reine SQL-Abfragen: Ссылка

Ursprüngliche Namen von Tabellen werden in dieser Frage der Einfachheit halber geändert, Spiel ist GamelistLeague, Team ist TeamInfo, und es gibt BatterStats und PitcherStats anstelle von einem PlayerStat

Die erste Abfrage aus den Protokollen ist diejenige, die in dieser Frage oben gezeigt wird (benannte Abfrage), die, wenn ich sie direkt in der Datenbank ausführe, alles nach Bedarf zurückgibt.

    
maximus 14.01.2015, 04:14
quelle

2 Antworten

22

Sie haben ein wohlbekanntes Problem, unter anderem das "N + 1 wählt". Kurz gesagt, tritt das "N + 1 selects" -Problem auf, wenn Sie eine übergeordnete Entität auswählen, und der Ruhezustand wird zusätzliche Auswahl für ein untergeordnetes Element vornehmen, das mit OneToOne zu dem übergeordneten Element verwandt wird. Wenn Sie also "N" Eltern-Kind-Datensätze in der Datenbank haben, erhält Hibernate alle Eltern mit einer Auswahl und dann jedes Kind in getrennten Auswahl, so dass insgesamt N + 1 wählt Es gibt zwei Ansätze für "N + 1" Problem im Ruhezustand:
1. "Join Fetch" alle OneToOne-Kinder.
2. Aktivieren Sie den Cache der zweiten Ebene und verwenden Sie die @Cache-Annotation für die untergeordneten OneToOne-Elemente.

Ihr Problem besteht darin, dass Sie nicht alle OneToOne-Childs "zusammenführen". Sie müssen alle, einschließlich der transitiven Kinder (Entitäten, auf die von Kindern selbst oder in der Sammlung verwiesen wird), "fetch" hinzufügen.

OneToOne zu faul zu machen (weil es standardmäßig eifrig ist), ist nur eine Teillösung, weil Hibernate nur dann eine Auswahl für ein Kind trifft, wenn Sie auf einen Getter auf dem Kind zugreifen, aber auf lange Sicht alle N selektiert.

    
outdev 20.01.2015, 21:47
quelle
1

Die sekundären Abfragen kommen von:

%Vor%

Also müssen Sie:

  1. Machen Sie alle Assoziationen LAZY. Standardmäßig sind alle @ManyToOne- und @OneToOne-Assoziationen EAGER, also ist es besser, sie zu haben LAZY und überschreiben nur den Abrufplan auf Abfragebasis.

  2. Entfernen Sie @Fetch(FetchMode.JOIN) , was im Wesentlichen eine EAGER-Abrufanweisung ist. In deinem Fall wird nicht nur die team2 Eigenschaft geholt, sondern auch ihre Spieler und Fähigkeiten.

Vlad Mihalcea 16.01.2015 07:38
quelle

Tags und Links