Ich bin ein Neuling in Java Persistence API und Hibernate.
Was ist der Unterschied zwischen FetchType.LAZY
und FetchType.EAGER
in der Java Persistence API?
Ich bin ein Neuling in Java Persistence API und Hibernate.
Was ist der Unterschied zwischen FetchType.LAZY
und FetchType.EAGER
in der Java Persistence API?
Antworten:
Manchmal haben Sie zwei Entitäten und es gibt eine Beziehung zwischen ihnen. Beispielsweise könnte eine Entität aufgerufen
University
und eine andere Entität aufgerufen werden,Student
und eine Universität könnte viele Studenten haben:Die Universitätsentität verfügt möglicherweise über einige grundlegende Eigenschaften wie ID, Name, Adresse usw. sowie über eine Sammlungseigenschaft namens "Studenten", die die Liste der Studenten für eine bestimmte Universität zurückgibt:
Wenn Sie jetzt eine Universität aus der Datenbank laden, lädt JPA die Felder für ID, Name und Adresse für Sie. Sie haben jedoch zwei Möglichkeiten, wie Schüler geladen werden sollen:
getStudents()
Methode der Universität aufrufen .Wenn eine Universität viele Studenten hat, ist es nicht effizient, alle ihre Studenten zusammen mit ihnen zu laden, insbesondere wenn sie nicht benötigt werden. In solchen Fällen können Sie erklären, dass Studenten geladen werden sollen, wenn sie tatsächlich gebraucht werden. Dies wird als verzögertes Laden bezeichnet.
Hier ist ein Beispiel, in dem
students
explizit markiert ist, dass es eifrig geladen werden soll:Und hier ist ein Beispiel, in dem
students
explizit markiert ist, dass es träge geladen werden soll:quelle
getStudents()
) in den Speicher geladen werden sollen. Dies ist jedoch manchmal nicht möglich, da diese Methode zu diesem Zeitpunkt nicht verfügbar ist aufgerufen wird, ist die Sitzung bereits geschlossen und die Entität getrennt. In ähnlicher Weise haben wir manchmal eine Client / Server-Architektur (z. B. Swing-Client / JEE-Server) und die Entitäten / DTOs werden über die Leitung an den Client übertragen, und in diesen Szenarien funktioniert das verzögerte Laden aufgrund der Art und Weise der Entitäten meistens nicht werden über das Kabel serialisiert.getStudents()
die Ergebnisse zwischengespeichert , wenn ich die Methode zum ersten Mal aufrufe? damit ich beim nächsten Mal schneller auf diese Ergebnisse zugreifen kann?Grundsätzlich,
quelle
EAGER
Das Laden von Sammlungen bedeutet, dass sie zum Zeitpunkt des Abrufs ihres übergeordneten Elements vollständig abgerufen werden. Wenn Sie also habenCourse
und habenList<Student>
, werden alle Schüler zum Zeitpunkt des Abrufs aus der DatenbankCourse
abgerufen.LAZY
Auf der anderen Seite bedeutet dies, dass der Inhalt vonList
nur abgerufen wird, wenn Sie versuchen, darauf zuzugreifen. Zum Beispiel durch einen Anrufcourse.getStudents().iterator()
. Durch Aufrufen einer beliebigen Zugriffsmethode aufList
wird ein Aufruf der Datenbank zum Abrufen der Elemente ausgelöst. Dies wird implementiert, indem ein Proxy um dasList
(oderSet
) erstellt wird. Für Ihre faulen Sammlungen sind die konkreten Typen also nichtArrayList
undHashSet
, sondernPersistentSet
undPersistentList
(oderPersistentBag
)quelle
course.getStudents()
, wird eine SQL-Abfrage ausgelöst (siehe auf der Konsole). Auch beim Lazy-Fetch-Typ passiert dasselbe. Also, was ist der Unterschied?fetchtype = LAZY
die Standardeinstellung gesetzt ist, auch wenn der Versuch, die Sammlung mit dem Getter Hibernete zu erhalten, einen Fehler auslöst, der mir sagt, dass es nicht ausgewertet werden kannIch kann Leistung und Speichernutzung berücksichtigen. Ein großer Unterschied besteht darin, dass die EAGER-Abrufstrategie die Verwendung von abgerufenen Datenobjekten ohne Sitzung ermöglicht. Warum?
Alle Daten werden abgerufen, wenn eifrig markierte Daten im Objekt vorhanden sind, wenn die Sitzung verbunden ist. Im Falle einer Strategie zum verzögerten Laden ruft das markierte Objekt zum verzögerten Laden jedoch keine Daten ab, wenn die Sitzung getrennt wird (nach der
session.close()
Anweisung). All dies kann durch einen Ruhezustand-Proxy erfolgen. Mit einer eifrigen Strategie können Daten nach Abschluss der Sitzung weiterhin verfügbar sein.quelle
Nach meinem Wissen hängen beide Arten des Abrufs von Ihren Anforderungen ab.
FetchType.LAZY
ist auf Anfrage (dh wenn wir die Daten benötigt haben).FetchType.EAGER
ist unmittelbar (dh bevor unsere Anforderung kommt, holen wir den Datensatz unnötig ab)quelle
Standardmäßig gilt für alle Sammlungs- und Zuordnungsobjekte die Abrufregel
FetchType.LAZY
und für andere Fälle folgt sie derFetchType.EAGER
Richtlinie.Kurz gesagt ,
@OneToMany
und@ManyToMany
Beziehungen rufen die zugehörigen Objekte (Sammlung und Karte) nicht implizit ab, sondern die Abrufoperation wird durch das Feld in@OneToOne
und@ManyToOne
diejenigen kaskadiert .(mit freundlicher Genehmigung: - objectdbcom)
quelle
Beide
FetchType.LAZY
undFetchType.EAGER
werden verwendet, um den Standardabrufplan zu definieren .Leider können Sie nur den Standardabrufplan für das LAZY-Abrufen überschreiben. Das Abrufen von EAGER ist weniger flexibel und kann zu vielen Leistungsproblemen führen .
Mein Rat ist, den Drang zu unterdrücken, Ihre Assoziationen zu EAGER zu machen, da das Abrufen in der Verantwortung der Abfragezeit liegt. Daher sollten alle Ihre Abfragen die Abrufanweisung verwenden, um nur das abzurufen, was für den aktuellen Geschäftsfall erforderlich ist.
quelle
Aus dem Javadoc :
ZB ist eifriger proaktiv als faul. Faulheit tritt nur beim ersten Gebrauch auf (wenn der Anbieter den Hinweis versteht), wohingegen bei eifrigen Dingen (möglicherweise) Dinge vorab abgerufen werden.
quelle
Der
Lazy
Abruftyp wird standardmäßig im Ruhezustand ausgewählt, es sei denn, Sie markieren denEager
Abruftyp explizit . Um genauer und prägnanter zu sein, kann der Unterschied wie folgt angegeben werden.FetchType.LAZY
= Dadurch werden die Beziehungen nur geladen, wenn Sie sie über die Getter-Methode aufrufen.FetchType.EAGER
= Dies lädt alle Beziehungen.Vor- und Nachteile dieser beiden Abruftypen.
Lazy initialization
Verbessert die Leistung, indem unnötige Berechnungen vermieden und der Speicherbedarf reduziert werden.Eager initialization
nimmt mehr Speicherplatz in Anspruch und die Verarbeitungsgeschwindigkeit ist langsam.Having said that, hängt von der Situation entweder eines dieser Initialisierung verwendet werden.
quelle
getMember
wird, die genau dem Namensmuster des Mitglieds entspricht?Book.java
Subject.java
HibernateUtil.java
Main.java
Überprüfen Sie die Methode retrieve () von Main.java. Wenn wir den Betreff erhalten , werden die mit Anmerkungen versehenen Sammlungslistenbücher träge
@OneToMany
geladen. Aber auf der anderen Seite, Bücher im Zusammenhang Vereinigung der Sammlung Themas , mit Anmerkungen versehen mit@ManyToOne
, Lasten eargerly (von[default][1]
für@ManyToOne
,fetchType=EAGER
). Wir können das Verhalten ändern, indem wir fetchType.EAGER auf@OneToMany
Subject.java oder fetchType.LAZY auf@ManyToOne
Books.java setzen.quelle
Quelle
quelle
Ich möchte diese Notiz zu dem hinzufügen, was "Kyung Hwan Min" oben gesagt hat.
Angenommen, Sie verwenden Spring Rest mit diesem einfachen Architekten:
Wenn Sie einige Daten an das Front-End zurückgeben möchten, erhalten Sie bei Verwendung
FetchType.LAZY
eine Ausnahme, nachdem Sie Daten an die Controller-Methode zurückgegeben haben, da die Sitzung im Service geschlossenJSON Mapper Object
ist und die Daten nicht abgerufen werden können.Es gibt drei gängige Optionen zur Lösung dieses Problems, die vom Design, der Leistung und dem Entwickler abhängen:
FetchType.EAGER
, damit die Sitzung bei der Controller-Methode noch aktiv ist.FetchType.LAZY
mit der Konvertermethode Daten vonEntity
einem anderen Datenobjekt zu übertragenDTO
und an den Controller zu senden. Es gibt also keine Ausnahme, wenn die Sitzung geschlossen wird.quelle
Hallo, ich habe 2 Fotos angehängt, um Ihnen das Verständnis zu erleichtern.
quelle
@ drop-shadow Wenn Sie den Ruhezustand verwenden, können
Hibernate.initialize()
Sie beim Aufrufen dergetStudents()
Methode Folgendes aufrufen :quelle
LAZY: Es ruft die untergeordneten Entitäten träge ab, dh zum Zeitpunkt des Abrufs der übergeordneten Entität ruft es nur den Proxy (erstellt von cglib oder einem anderen Dienstprogramm) der untergeordneten Entitäten ab, und wenn Sie auf eine Eigenschaft der untergeordneten Entität zugreifen, wird es tatsächlich im Ruhezustand abgerufen.
EAGER: Es ruft die untergeordneten Entitäten zusammen mit den übergeordneten Entitäten ab.
Zum besseren Verständnis gehen Sie zur Jboss-Dokumentation oder verwenden Sie sie
hibernate.show_sql=true
für Ihre App und überprüfen Sie die vom Ruhezustand ausgegebenen Abfragen.quelle