it-swarm.com.de

Unterschied zwischen JOIN und JOIN FETCH im Ruhezustand

Bitte helfen Sie mir zu verstehen, wo ein regulärer JOIN und wo ein JOIN-FETCH verwendet werden soll.

Zum Beispiel, wenn wir diese beiden Abfragen haben

FROM Employee emp
JOIN emp.department dep

und

FROM Employee emp
JOIN FETCH emp.department dep

Gibt es einen Unterschied zwischen ihnen? Wenn ja, welches wann?

145
abbas

In diesen beiden Abfragen verwenden Sie JOIN, um alle Mitarbeiter abzufragen, denen mindestens eine Abteilung zugeordnet ist.

Der Unterschied ist jedoch, dass Sie in der ersten Abfrage nur die Mitarbeiter für den Ruhezustand zurückgeben. In der zweiten Abfrage geben Sie die Mitarbeiter und aller zugeordneten Abteilungen zurück.

Wenn Sie also die zweite Abfrage verwenden, müssen Sie keine neue Abfrage ausführen, um erneut auf die Datenbank zuzugreifen und die Abteilungen der einzelnen Mitarbeiter anzuzeigen.

Sie können die zweite Abfrage verwenden, wenn Sie sicher sind, dass Sie die Abteilung jedes Mitarbeiters benötigen. Wenn Sie die Abteilung nicht benötigen, verwenden Sie die erste Abfrage.

Ich empfehle diesen Link zu lesen, wenn Sie eine WHERE-Bedingung anwenden müssen (was Sie wahrscheinlich benötigen werden): Wie man JPQL "join fetch" mit "where" -Klausel als JPA 2 CriteriaQuery richtig ausdrückt?

Update

Wenn Sie fetch nicht verwenden und die Abteilungen weiterhin zurückgegeben werden, liegt dies daran, dass Ihre Zuordnung zwischen Mitarbeiter und Abteilung (a @OneToMany) werden mit FetchType.EAGER. In diesem Fall kann jede HQL-Abfrage (mit fetch oder nicht) mit FROM Employee bringt alle Abteilungen. Denken Sie daran, dass alle Zuordnungen * ToOne (@ManyToOne und @OneToOne) sind standardmäßig EAGER.

151
Dherik

in dieser link ich erwähnte vorher auf dem kommentar, lies diesen teil:

Ein Fetch-Join ermöglicht die Initialisierung von Assoziationen oder Wertesammlungen zusammen mit ihren übergeordneten Objekten mit einer einzigen Auswahl. Dies ist besonders nützlich bei einer Sammlung. Es überschreibt effektiv die Outer Join- und Lazy-Deklarationen der Mapping-Datei für Assoziationen und Collections.

dieses "JOIN FETCH" hat seine Wirkung, wenn Sie die Eigenschaft (fetch = FetchType.LAZY) für eine Sammlung innerhalb einer Entität haben (Beispiel unten).

Und es wirkt sich nur die Methode aus, "wann die Abfrage erfolgen soll". Und Sie müssen auch wissen dies :

im Ruhezustand gibt es zwei orthogonale Begriffe: Wann und wie wird die Assoziation abgerufen? Es ist wichtig, dass Sie sie nicht verwechseln. Wir verwenden Fetch, um die Leistung zu optimieren. Wir können Lazy verwenden, um einen Vertrag zu definieren, für den immer Daten in einer getrennten Instanz einer bestimmten Klasse verfügbar sind.

wann wird die Assoziation geholt -> Ihr "FETCH" -Typ

wie wird es geholt -> Join/select/Subselect/Batch

In Ihrem Fall hat FETCH nur dann Auswirkungen, wenn Sie in Employee eine Abteilung festgelegt haben, die in der Entität ungefähr so ​​aussieht:

@OneToMany(fetch = FetchType.LAZY)
private Set<Department> department;

wenn du verwendest

FROM Employee emp
JOIN FETCH emp.department dep

sie erhalten emp und emp.dep. Wenn Sie Fetch nicht verwendet haben, können Sie immer noch emp.dep Der Ruhezustand verarbeitet jedoch eine andere Auswahl in der Datenbank, um diese Gruppe von Abteilungen abzurufen.

es ist also nur eine Frage der Leistungsoptimierung, ob Sie das gesamte Ergebnis (ob Sie es benötigen oder nicht) in einer einzelnen Abfrage erhalten möchten (eifriges Abrufen) oder ob Sie es letztendlich abfragen möchten, wenn Sie es benötigen (verzögertes Abrufen).

Verwenden Sie das eifrige Abrufen, wenn Sie mit einer Auswahl (einer großen Abfrage) kleine Daten abrufen müssen. Oder verwenden Sie Lazy Fetching, um das abzufragen, was Sie zuletzt benötigen (viele kleinere Abfragen).

benutze fetch wenn:

  • no large unnötig Sammlung/Set in dieser Entität, die Sie gleich erhalten

  • kommunikation vom Anwendungsserver zum Datenbankserver zu weit und brauchen lange Zeit

  • sie benötigen diese Sammlung möglicherweise später, wenn Sie keinen Zugriff darauf haben ( outside der transactional Methode/Klasse)

55
Angga

Wenn für die @oneToOne-Zuordnung FetchType.LAZY festgelegt ist und Sie die zweite Abfrage verwenden (da Abteilungsobjekte als Teil von Mitarbeiterobjekten geladen werden müssen), werden im Ruhezustand Abfragen ausgegeben, um Abteilungsobjekte für jedes einzelne Mitarbeiterobjekt abzurufen es holt von DB. Später im Code können Sie über die einwertige Zuordnung Mitarbeiter zu Abteilung auf Abteilungsobjekte zugreifen, und Hibernate gibt keine Abfrage aus, um das Abteilungsobjekt für den angegebenen Mitarbeiter abzurufen. Denken Sie daran, dass der Ruhezustand weiterhin Abfragen ausgibt, die der Anzahl der abgerufenen Mitarbeiter entsprechen. Hibernate gibt in beiden obigen Abfragen die gleiche Anzahl von Abfragen aus, wenn Sie auf Abteilungsobjekte aller Employee-Objekte zugreifen möchten

4
Bunti

Dherik: Ich bin mir nicht sicher, was Sie sagen, wenn Sie Fetch nicht verwenden, wird das Ergebnis vom Typ sein: List<Object[ ]> bedeutet eine Liste von Objekttabellen und keine Liste von Mitarbeitern.

Object[0] refers an Employee entity 
Object[1] refers a Departement entity 

Wenn Sie fetch verwenden, gibt es nur eine Auswahl und das Ergebnis ist die Liste von Employee List<Employee> mit der Liste der Abteilungen. Es überschreibt die Lazy-Deklaration der Entität.

1
Bilal BBB