Was ist verzögertes Laden im Ruhezustand?


177

Was ist verzögertes Laden in Java? Ich verstehe den Prozess nicht. Kann mir jemand helfen, den Prozess des faulen Ladens zu verstehen?

Antworten:


267

Angenommen, Sie haben einen Elternteil und dieser Elternteil hat eine Sammlung von Kindern. Der Ruhezustand kann jetzt die untergeordneten Elemente "faul laden", was bedeutet, dass beim Laden des übergeordneten Elements nicht alle untergeordneten Elemente geladen werden. Stattdessen werden sie geladen, wenn Sie dazu aufgefordert werden. Sie können dies entweder explizit anfordern oder, und dies ist weitaus häufiger, der Ruhezustand lädt sie automatisch, wenn Sie versuchen, auf ein untergeordnetes Element zuzugreifen.

Lazy-Loading kann dazu beitragen, die Leistung erheblich zu verbessern, da die Kinder häufig nicht benötigt werden und sie daher nicht geladen werden.

Achten Sie auch auf das n + 1-Problem. Im Ruhezustand werden nicht alle untergeordneten Elemente geladen, wenn Sie auf die Sammlung zugreifen. Stattdessen wird jedes Kind einzeln geladen. Beim Durchlaufen der Sammlung wird für jedes untergeordnete Element eine Abfrage ausgeführt. Um dies zu vermeiden, können Sie den Ruhezustand dazu bringen, alle untergeordneten Elemente gleichzeitig zu laden, z. B. indem Sie parent.getChildren (). Size () aufrufen.


5
Alternativ sollte Hibernate.initialize (parent.getChildren ()) verwendet werden
HakunaMatata

18
Die Aussage "Wenn Sie auf die Sammlung zugreifen ... wird jedes Kind einzeln geladen" ist tatsächlich völlig ungenau. Es ist eigentlich das genaue Gegenteil. Jede Dereferenzierung von parent.getChildren () führt dazu, dass Hibernate alle untergeordneten Elemente in der Auflistung in einer Datenbankabfrage lädt. Es sei denn, Sie haben den ganz besonderen "extra faulen" Hinweis zum faulen Laden verwendet. Oder es sei denn, Sie zwischenspeichern die Sammlung im Cache der zweiten Ebene und die zugehörigen untergeordneten Elemente werden nicht ebenfalls zwischengespeichert.
Steve Ebersole

Oh, Stapelüberlauf - beste Antwort am Ende der Seite ;-)
Piotrek Hryciuk

76

„Lazy Loading“ bedeutet , dass ein Unternehmen geladen wird nur , wenn Sie tatsächlich die Einrichtung , welche die Zugriffe erste Mal.

Das Muster ist wie folgt:

public Entity getEntity() {
    if (entity == null) {
        entity = loadEntity();
    }
    return entity;
}

Dies spart die Kosten für das Vorladen / Vorfüllen aller Entitäten in einem großen Datensatz im Voraus, während Sie schließlich nicht alle benötigen .

Im Ruhezustand können Sie konfigurieren, dass eine Sammlung untergeordneter Entitäten träge geladen wird. Das eigentliche verzögerte Laden erfolgt dann innerhalb der Methoden, PersistentSetdie Hibernate "unter den Hauben" verwendet, um die Sammlung von Entitäten als zuzuweisen Set.

Z.B

public class Parent {
    private Set<Child> children;

    public Set<Child> getChildren() {
        return children;
    }
}

.

public void doSomething() {
    Set<Child> children = parent.getChildren(); // Still contains nothing.

    // Whenever you call one of the following (indirectly), 
    // Hibernate will start to actually load and fill the set.
    children.size();
    children.iterator();
}

25

Martin Fowler definiert das Lazy Load- Muster in Patterns of Enterprise Application Architecture als solches:

Ein Objekt, das nicht alle benötigten Daten enthält, aber weiß, wie man sie erhält.

Wenn Sie also ein bestimmtes Objekt laden , besteht die Idee darin, die zugehörigen Objekte, die Sie möglicherweise nicht sofort verwenden, um die zugehörigen Leistungskosten zu sparen , nicht eifrig zu laden . Stattdessen werden die zugehörigen Objekte nur bei Verwendung geladen.

Dies ist kein spezifisches Muster für Datenzugriff und Ruhezustand, aber es ist besonders nützlich in solchen Bereichen, und der Ruhezustand unterstützt das verzögerte Laden von Eins-zu-Viele-Zuordnungen und Einzelpunkt-Zuordnungen (Eins-zu-Eins und Viele-zu-Eins) unter bestimmten Bedingungen. Die verzögerte Interaktion wird in Kapitel 19 der Hibernate 3.0-Referenzdokumentation ausführlicher erläutert .


15

Standardmäßig ist das verzögerte Laden wahr. Faules Laden bedeutet, dass die ausgewählte Abfrage nicht in die Datenbank gelangt, wenn sie ausgeführt wird. Es wartet auf die Getter-Funktion, dh wenn es erforderlich ist, wird es aus der Datenbank abgerufen. Zum Beispiel: Sie sind ein Elternteil, der ein Kind mit vielen Spielsachen hat. Aber das aktuelle Problem ist, wann immer Sie ihn anrufen (wir nehmen an, Sie haben einen Jungen), kommt er auch mit all seinen Spielsachen zu Ihnen. Dies ist ein Problem, da Sie nicht möchten, dass er seine Spielsachen ständig mit sich herumträgt. Als rationaler Elternteil definieren Sie das Spielzeug des Kindes als faul. Wann immer Sie ihn anrufen, kommt er einfach ohne sein Spielzeug zu Ihnen.


11

Das verzögerte Abrufen entscheidet, ob untergeordnete Objekte beim Laden des übergeordneten Objekts geladen werden sollen. Sie müssen diese Einstellung für die entsprechende Zuordnungsdatei für den Ruhezustand der übergeordneten Klasse vornehmen. Lazy = true(bedeutet, kein Kind zu laden) Standardmäßig ist das verzögerte Laden der untergeordneten Objekte wahr.

Dadurch wird sichergestellt, dass die getChild()untergeordneten Objekte nicht geladen werden, es sei denn, sie werden in der Anwendung explizit durch Aufrufen der Methode auf parent aufgerufen. In diesem Fall gibt der Ruhezustand einen neuen Datenbankaufruf aus, um das getChild()untergeordnete Objekt zu laden, wenn das übergeordnete Objekt tatsächlich aufgerufen wird.

In einigen Fällen müssen Sie jedoch die untergeordneten Objekte laden, wenn die übergeordneten Objekte geladen werden. Machen Sie einfach lazy = false und der Ruhezustand lädt das untergeordnete Element, wenn das übergeordnete Element aus der Datenbank geladen wird.

Beispiel: Wenn Sie eine TABELLE haben? Der MITARBEITER ist dem Mitarbeiterobjekt zugeordnet und enthält eine Reihe von Adressobjekten. Übergeordnete Klasse: Mitarbeiterklasse, untergeordnete Klasse: Adressklasse

public class Employee { 
private Set address = new HashSet(); // contains set of child Address objects 
public Set getAddress () { 
return address; 
} 
public void setAddresss(Set address) { 
this. address = address; 
} 
} 

In der Datei Employee.hbm.xml

<set name="address" inverse="true" cascade="delete" lazy="false"> 
<key column="a_id" /> 
<one-to-many class="beans Address"/> 
</set> 

In der obigen Konfiguration. Wenn lazy="false": - Wenn Sie das Employee-Objekt laden, wird auch die Adresse des untergeordneten Objekts geladen und auf die Methode setAddresss () gesetzt. Wenn Sie employee.getAdress () aufrufen, werden geladene Daten zurückgegeben. Kein neuer Datenbankaufruf.

Wenn lazy="true": - Dies ist die Standardkonfiguration. Wenn Sie nicht erwähnen, dann betrachten Sie den Ruhezustand als faul = wahr. Wenn Sie das Employee-Objekt laden, wird die Adresse des untergeordneten Objekts nicht geladen. Sie benötigen einen zusätzlichen Aufruf der Datenbank, um Adressobjekte abzurufen. Wenn Sie employee.getAdress()dann anrufen , wird diese Zeitdatenbankabfrage ausgelöst und gibt Ergebnisse zurück. Neuer Datenbankaufruf.


Mitarbeiter und Adresse haben in diesem Szenario keine Eltern-Kind-Beziehung. Es ist eine Beziehung !
Ram

Dies ist Aggregation, keine Vererbung.
Rishi

11

In der Sprache des Laien ist es, als würden Sie einen Kuchen backen und benötigen 5-10 Zutaten aus dem Kühlschrank. Sie haben zwei Möglichkeiten, alle Zutaten aus dem Kühlschrank zu holen und auf Ihre Küchenplattform zu stellen oder das gewünschte Produkt mitzubringen, wenn Sie es benötigen.

In ähnlicher Weise rufen Sie beim eifrigen Laden zuerst alle Informationen über Bohnen und die zugehörigen Klassen ab (nicht Kind oder ist eine Beziehung, sondern hat eine Beziehung, dh Kuchen hat Mehl, hat Milch, hat Sahne usw.) und im Falle eines faulen Ladens zuerst Sie bringen nur die Kennung und die Werte mit, die aus derselben Tabelle stammen (notwendige Zutaten, die Sie im Falle eines Kuchens zuerst in Ihrer Schüssel benötigen). Alle Informationen, die aus anderen Tabellen stammen, werden bei Bedarf / Verwendung abgerufen.


8

Faules Laden? Nun, es bedeutet einfach, dass untergeordnete Datensätze nicht sofort abgerufen werden, sondern automatisch, sobald Sie versuchen, darauf zuzugreifen.


3

Die verzögerte Einstellung entscheidet, ob untergeordnete Objekte beim Laden des übergeordneten Objekts geladen werden sollen. Sie müssen diese Einstellung für die entsprechende Zuordnungsdatei im Ruhezustand der übergeordneten Klasse vornehmen. Lazy = true (bedeutet, dass untergeordnete Objekte nicht geladen werden) Standardmäßig ist das verzögerte Laden der untergeordneten Objekte true . Dadurch wird sichergestellt, dass die untergeordneten Objekte nicht geladen werden, es sei denn, sie werden in der Anwendung explizit aufgerufen, indem die Methode getChild () auf parent aufgerufen wird. In diesem Fall gibt der Ruhezustand einen neuen Datenbankaufruf aus, um das untergeordnete Objekt zu laden, wenn getChild () tatsächlich auf dem übergeordneten Objekt aufgerufen wird Aber in einigen Fällen müssen Sie die untergeordneten Objekte laden, wenn die übergeordneten Objekte geladen werden. Machen Sie einfach lazy = false und der Ruhezustand lädt das untergeordnete Element, wenn das übergeordnete Element aus der Datenbank geladen wird. Beispiellazy = true (Standard) Das untergeordnete Adressadresse der Benutzerklasse kann verzögert werden, wenn es nicht häufig benötigt wird.


3

Durch verzögertes Laden können Sie das Abrufen von Zuordnungen verschieben oder die Abrufstrategie besser steuern.

Wenn Sie das Laden von EAGER verwenden, definieren Sie einen globalen Abrufplan, der zum Zeitpunkt der Abfrage nicht überschrieben werden kann. Dies bedeutet, dass Sie sich auf eine Entscheidung beschränken, die Sie beim Entwerfen Ihres Entitätsmodells getroffen haben. Das EAGER-Abrufen ist ein Codegeruch , da die Abrufstrategie eine Abfragezeitrichtlinie ist und sich von einem Geschäftsanwendungsfall zum anderen unterscheiden kann.

Die Abrufstrategie ist ein sehr wichtiger Aspekt, da zu viel EAGER-Abruf schwerwiegende leistungsbezogene Probleme verursachen kann.


2

Lazy Loading ist ein Entwurfsmuster, das üblicherweise in der Computerprogrammierung verwendet wird, um die Initialisierung eines Objekts bis zu dem Punkt zu verschieben, an dem es benötigt wird. Es kann zur Effizienz des Programmbetriebs beitragen, wenn es ordnungsgemäß und angemessen verwendet wird

Wikipedia

Link von Lazy Loading von hibernate.org


1

Nun, es bedeutet einfach, Daten zu laden, die Sie derzeit benötigen, anstatt eine ganze Reihe von Daten auf einmal zu laden, die Sie jetzt nicht verwenden werden. Dadurch wird die Ladezeit der Anwendung schneller als gewöhnlich.


0

Hiberante unterstützt die Funktion der verzögerten Initialisierung sowohl für Entitäten als auch für Sammlungen. Die Hibernate-Engine lädt nur die Objekte, nach denen wir abfragen, und keine anderen Entites oder Sammlungen.

lazy = "false" Standardmäßig wird beim Laden der Initialisierung erwähnt, dass das einzige untergeordnete Element faul ist. Im Fall von true, dass das übergeordnete Element geladen wird, wird das untergeordnete Element nicht unterstützt


0

Die verzögerte Einstellung entscheidet, ob untergeordnete Objekte beim Laden des übergeordneten Objekts geladen werden sollen. Sie müssen diese Einstellung für die entsprechende Zuordnungsdatei für den Ruhezustand der übergeordneten Klasse vornehmen. Lazy = true (bedeutet, dass untergeordnete Objekte nicht geladen werden) Standardmäßig ist das verzögerte Laden der untergeordneten Objekte true .


0

Überraschenderweise spricht keine der Antworten darüber, wie dies durch den Ruhezustand hinter den Bildschirmen erreicht wird.

Lazy Loading ist ein Entwurfsmuster, das aus Leistungsgründen im Ruhezustand effektiv verwendet wird und folgende Techniken umfasst.


1. Bytecode-Instrumentierung :

Verbessert die Basisklassendefinition um Hooks im Ruhezustand , um alle Aufrufe dieses Entitätsobjekts abzufangen.

Fertig entweder zur Kompilierungszeit oder zur Laufzeit [Laden]

1.1 Kompilierungszeit

  • Operation nach der Kompilierungszeit

  • Meistens von Maven / Ant Plugins

1.2 Laufzeit

  • Wenn keine Instrumentierung zur Kompilierungszeit durchgeführt wird, wird diese zur Laufzeit mithilfe von Bibliotheken wie javassist erstellt

2. Proxies

Das Entitätsobjekt, das Hibernate zurückgibt, ist ein Proxy des realen Typs.

Siehe auch: Javassist. Was ist die Hauptidee und wo wirklich verwendet?

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.