Bitte helfen Sie mir zu verstehen, wo ein regulärer JOIN und wo ein JOIN FETCH zu verwenden ist.
Zum Beispiel, wenn wir diese zwei 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, welche sollte man wann verwenden?
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 Hibernate zurückgeben. In der zweiten Abfrage geben Sie die Mitarbeiter und alle zugehörigen Abteilungen zurück.
Wenn Sie also die zweite Abfrage verwenden, müssen Sie keine neue Abfrage durchführen, um die Abteilungen jedes Mitarbeiters in der Datenbank zu finden.
Sie können die zweite Abfrage verwenden, wenn Sie sicher sind, dass Sie die Abteilungen der einzelnen Mitarbeiter benötigen. Wenn Sie die Abteilung nicht benötigen, verwenden Sie die erste Abfrage.
Ich empfehle Ihnen, diesen Link zu lesen, wenn Sie eine WHERE-Bedingung anwenden müssen (was Sie wahrscheinlich brauchen werden): https://stackoverflow.com/questions/5816417/how-to-properly-express-jpql-join-fetch-with-where-clause-as-jpa-2-criteriaq
Aktualisierung
Wenn Sie fetch
nicht verwenden und die Abteilungen weiterhin zurückgegeben werden, liegt das daran, dass Ihr Mapping zwischen Mitarbeiter und Abteilung (ein @OneToMany
) mit FetchType.EAGER
eingestellt ist. In diesem Fall wird jede HQL-Abfrage (mit Fetch
oder nicht) mit FROM Employee
alle Abteilungen liefern. Denken Sie daran, dass alle Mappings *ToOne (@ManyToOne
und @OneToOne
) standardmäßig EAGER sind.
in diesem Link, den ich zuvor in einem Kommentar erwähnt habe, lesen Sie diesen Teil:
Eine "fetch" Verknüpfung ermöglicht es, Assoziationen oder Sammlungen von Werten zu zusammen mit ihren übergeordneten Objekten mit einem einzigen Select initialisiert werden. Dies ist besonders nützlich im Falle einer Sammlung. Es überschreibt effektiv die äußere Verknüpfung und Lazy-Deklarationen der Mapping-Datei für Assoziationen und Sammlungen.
Dieser "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 ist nur Wirkung die Methode der "wenn die Abfrage passieren sollte". Und Sie müssen auch dies kennen:
hibernate haben zwei orthogonale Begriffe : wann wird die Assoziation abgeholt und wie abgerufen wird. Es ist wichtig, dass Sie sie nicht verwechseln. Wir verwenden fetch, um die Leistung zu optimieren. Wir können lazy verwenden, um einen Vertrag darüber zu definieren welche Daten sind immer in jeder losgelösten Instanz einer bestimmten Klasse verfügbar sind.
wann wird die Assoziation geholt - > Ihr "FETCH" Typ
wie wird sie abgerufen - > Join/Select/Subselect/Batch
In Ihrem Fall hat FETCH nur dann einen Effekt, wenn Sie die Abteilung als Set innerhalb von Employee haben, etwa so in der Entität:
@OneToMany(fetch = FetchType.LAZY)
private Set<Department> department;
wenn Sie verwenden
FROM Employee emp
JOIN FETCH emp.department dep
erhalten Sie emp
und emp.dep
. Wenn Sie fetch nicht verwenden, können Sie immer noch emp.dep
erhalten, aber Hibernate verarbeitet einen weiteren Select in der Datenbank, um diesen Satz von Abteilungen zu erhalten.
Es ist also nur eine Frage der Leistungsoptimierung, ob Sie alle Ergebnisse (ob Sie sie brauchen oder nicht) in einer einzigen Abfrage erhalten wollen (eager fetching) oder ob Sie sie erst später abfragen wollen, wenn Sie sie brauchen (lazy fetching).
Verwenden Sie eager fetching, wenn Sie kleine Daten mit einem select (einer großen Abfrage) abrufen müssen. Oder verwenden Sie "lazy fetching", um das abzufragen, was Sie später benötigen (viele kleinere Abfragen).
fetch verwenden, wenn:
keine große unbenötigte Sammlung/Sammlung innerhalb der Entität, die Sie abrufen wollen
die Kommunikation vom Anwendungsserver zum Datenbankserver zu weit ist und viel Zeit benötigt
Sie benötigen diese Sammlung möglicherweise später, wenn Sie keinen Zugriff darauf haben (außerhalb der transaktionalen Methode/Klasse)
Dherik: Ich bin mir nicht sicher, was Sie sagen, wenn Sie don' t verwenden fetch das Ergebnis wird vom Typ sein: List<Object[ ]>
, die eine Liste von Object-Tabellen und nicht eine Liste der Mitarbeiter bedeutet.
Object[0] refers an Employee entity
Object[1] refers a Departement entity
Wenn Sie fetch verwenden, gibt es nur ein select und das Ergebnis ist die Liste von Employee List<Employee>
, die die Liste der Abteilungen enthält. Sie setzt die träge Deklaration der Entität außer Kraft.