Co to jest leniwe ładowanie w Hibernate?

178

Co to jest leniwe ładowanie w Javie? Nie rozumiem tego procesu. Czy ktoś może mi pomóc zrozumieć proces leniwego ładowania?

biegun
źródło

Odpowiedzi:

268

Załóżmy, że masz rodzica i że rodzic ma kolekcję dzieci. Hibernacja może teraz "leniwie ładować" dzieci, co oznacza, że ​​w rzeczywistości nie ładuje wszystkich dzieci podczas ładowania rodzica. Zamiast tego ładuje je na żądanie. Możesz zażądać tego wyraźnie lub, co jest znacznie częstsze, hibernacja załaduje je automatycznie, gdy spróbujesz uzyskać dostęp do dziecka.

Leniwe ładowanie może znacznie poprawić wydajność, ponieważ często nie będziesz potrzebować dzieci i nie będą one ładowane.

Uważaj także na problem n + 1. Hibernate w rzeczywistości nie załaduje wszystkich elementów podrzędnych, gdy uzyskasz dostęp do kolekcji. Zamiast tego załaduje każde dziecko indywidualnie. Podczas iteracji po kolekcji powoduje to zapytanie dla każdego dziecka. Aby tego uniknąć, możesz oszukać hibernację i załadować wszystkie dzieci jednocześnie, np. Wywołując parent.getChildren (). Size ().

Thomas Lötzer
źródło
5
Alternatywnie należy użyć Hibernate.initialize (parent.getChildren ())
HakunaMatata.
18
Stwierdzenie „kiedy uzyskasz dostęp do kolekcji… załaduje ona każde dziecko z osobna” jest w rzeczywistości całkowicie niedokładne. W rzeczywistości jest dokładnie odwrotnie. Każde wyłuskiwanie klasy parent.getChildren () spowoduje, że Hibernate załaduje wszystkie elementy podrzędne w kolekcji w jednym zapytaniu bazy danych. Chyba że użyłeś bardzo specjalnej wskazówki "bardzo leniwe" leniwe ładowanie. Lub chyba że buforujesz kolekcję w pamięci podręcznej drugiego poziomu, a powiązane elementy podrzędne również nie są buforowane.
Steve Ebersole,
Och, przepełnienie stosu - najlepsza odpowiedź na dole strony ;-)
Piotrek Hryciuk
76

„Leniwe ładowanie” oznacza, że ​​jednostka zostanie załadowana tylko wtedy, gdy faktycznie uzyskasz do niej dostęp po raz pierwszy .

Wzór jest tak:

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

Oszczędza to koszt wstępnego ładowania / wstępnego wypełniania wszystkich jednostek w dużym zbiorze danych, podczas gdy w rzeczywistości nie potrzebujesz ich wszystkich .

W Hibernate można skonfigurować leniwe ładowanie kolekcji jednostek podrzędnych. Rzeczywisty leniwy ładowanie odbywa się wtedy wewnątrz metod na PersistentSetktóre Hibernate zastosowań „pod kapturami” przypisać zbiór podmiotów jak Set.

Na przykład

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();
}
BalusC
źródło
25

Martin Fowler definiuje wzorzec Lazy Load w Patterns of Enterprise Application Architecture jako taki:

Obiekt, który nie zawiera wszystkich potrzebnych danych, ale wie, jak je zdobyć.

Tak więc podczas ładowania danego obiektu chodzi o to, aby nie ładować z ochotą powiązanych obiektów, których nie można użyć natychmiast, aby zaoszczędzić na związanych z tym kosztach wydajności. Zamiast tego powiązane obiekty zostaną załadowane tylko wtedy, gdy są używane.

Nie jest to wzorzec specyficzny dla dostępu do danych i hibernacji, ale jest szczególnie przydatny w takich polach, a Hibernate obsługuje leniwe ładowanie asocjacji jeden do wielu i skojarzeń jednopunktowych (jeden do jednego i wiele do jednego) również pod pewnymi warunkami. Leniwe interakcje omówiono bardziej szczegółowo w rozdziale 19 dokumentacji referencyjnej Hibernate 3.0.

Pascal Thivent
źródło
15

Domyślnie leniwe ładowanie jest prawdziwe. Leniwe ładowanie oznacza, że ​​po wykonaniu zapytania wybierającego nie trafi ono do bazy danych. Będzie czekał na funkcję getter, tzn. Kiedy tego potrzebowaliśmy, pobierze z bazy danych. na przykład: jesteś rodzicem, który ma dziecko z dużą ilością zabawek. Ale aktualnym problemem jest to, że za każdym razem, gdy dzwonisz do niego (zakładamy, że masz chłopca), przychodzi do ciebie również ze wszystkimi swoimi zabawkami. Teraz jest to problem, ponieważ nie chcesz, aby przez cały czas nosił swoje zabawki. Więc będąc racjonalnym rodzicem, idź naprzód i określ zabawki dziecka jako LENIWE. Teraz, kiedy do niego dzwonisz, przychodzi do ciebie bez zabawek.

Chandresh Solanki
źródło
11

Leniwe pobieranie decyduje, czy załadować obiekty podrzędne podczas ładowania obiektu nadrzędnego. Musisz zrobić to ustawienie odpowiedniego pliku odwzorowania hibernacji klasy nadrzędnej. Lazy = true(czyli nie ładować dziecka) Domyślnie leniwe ładowanie obiektów potomnych jest prawdziwe.

Upewnij się, że obiekty potomne nie są ładowane, chyba że są jawnie wywoływane w aplikacji przez wywołanie getChild()metody na rodzicu.W tym przypadku hibernacja generuje nowe wywołanie bazy danych, aby załadować dzieckogetChild() jest aktywnie wywoływane na obiekcie Parent.

Ale w niektórych przypadkach musisz załadować obiekty podrzędne, gdy ładowany jest rodzic. Po prostu ustaw lazy = false, a hibernacja załaduje dziecko, gdy rodzic zostanie załadowany z bazy danych.

Przykład: jeśli masz TABELĘ? EMPLOYEE zmapowany na obiekt Employee i zawiera zestaw obiektów Address. Klasa nadrzędna: klasa pracownika, klasa podrzędna: klasa adresowa

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; 
} 
} 

W pliku Employee.hbm.xml

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

W powyższej konfiguracji. Jeśli lazy="false": - kiedy ładujesz obiekt Employee, tym razem obiekt podrzędny Address jest również ładowany i ustawiany na metodę setAddresss (). Jeśli wywołasz Employer.getAdress (), załadowane dane zostaną zwrócone. Brak nowego wywołania bazy danych.

Jeśli lazy="true": - To jest domyślna konfiguracja. Jeśli nie wspomnisz, hibernuj, rozważ leniwy = prawda. kiedy ładujesz obiekt pracownika, gdy adres obiektu podrzędnego nie jest ładowany. Potrzebujesz dodatkowego połączenia z bazą danych, aby uzyskać adresy obiektów. Jeśli zadzwonisz, employee.getAdress()wtedy zapytanie bazy danych zostanie uruchomione i zwróci wyniki. Nowe połączenie z bazą danych.

Bhavin Shah
źródło
Pracownik i adres nie mają relacji rodzic-dziecko w tym scenariuszu. To jest związek typu „ma-a” !
Ram
To jest agregacja, a nie dziedziczenie.
Rishi
11

Mówiąc językiem laika, to tak, jakbyś robił ciasto i potrzebujesz 5-10 składników z lodówki. Masz dwie możliwości: weź wszystkie składniki z lodówki i połóż je na kuchennym blacie lub przynieś żądany przedmiot, kiedy potrzebujesz.

Podobnie, przy szybkim ładowaniu pobierasz wszystkie informacje o fasoli i jej klasach powiązanych (nie jest to związek potomny lub jest-relacją, ale ma związek, np. Ciasto ma mąkę, ma mleko, ma śmietanę itp.), A w przypadku leniwego ładowania najpierw przynosisz tylko jego identyfikator i wartości, które pochodzą z tego samego stołu (niezbędne składniki, które najpierw będziesz potrzebować w swojej misce w przypadku ciasta). Wszystkie informacje pochodzące z innych tabel zostaną pobrane w razie potrzeby / użycia.

Keyur
źródło
8

Powolne ładowanie? Cóż, oznacza to po prostu, że rekordy podrzędne nie są pobierane natychmiast, ale automatycznie, gdy tylko spróbujesz uzyskać do nich dostęp.

Steffen
źródło
4

Ładowanie z opóźnieniem umożliwia odroczenie pobierania skojarzeń lub lepszą kontrolę nad strategią pobierania.

Używając ładowania EAGER, definiujesz globalny plan pobierania, którego nie można zastąpić w czasie zapytania, co oznacza, że ​​jesteś ograniczony do decyzji podjętej podczas projektowania modelu jednostki. EAGER ściągam to zapach kod , ponieważ strategia Pobieranie jest polityka zapytań czas i może się różnić od przypadku zastosowań biznesowych do drugiego.

Strategia Pobieranie jest bardzo ważnym aspektem, ponieważ zbyt dużo EAGER Pobieranie może spowodować poważne problemy z wydajnością związane.

Vlad Mihalcea
źródło
3

Ustawienie Lazy decyduje, czy załadować obiekty podrzędne podczas ładowania obiektu nadrzędnego. Należy to zrobić, ustawiając odpowiedni plik odwzorowania hibernacji klasy nadrzędnej. . Dzięki temu obiekty potomne nie zostaną załadowane, chyba że zostaną jawnie wywołane w aplikacji przez wywołanie metody getChild () na rodzicu. Jednak w niektórych przypadkach trzeba załadować obiekty podrzędne, gdy wczytuje się obiekt macierzysty. Po prostu ustaw lazy = false, a hibernacja załaduje dziecko, gdy rodzic zostanie załadowany z bazy danych.Exampleslazy = true (domyślnie) Adres potomny klasy User może być leniwy, jeśli nie jest często wymagany.

Siva Chimpiri
źródło
2

Leniwe ładowanie to wzorzec projektowy powszechnie używany w programowaniu komputerowym do odroczenia inicjalizacji obiektu do momentu, w którym jest to potrzebne. Właściwie i odpowiednio wykorzystany może przyczynić się do efektywności działania programu

Wikipedia

Link do leniwego ładowania ze strony hibernate.org

Diego Dias
źródło
1

Cóż, oznacza to po prostu ładowanie danych, których obecnie potrzebujesz, zamiast ładowania całej masy danych naraz, których nie będziesz teraz używać. Dzięki temu czas ładowania aplikacji jest szybszy niż zwykle.

Abhinaya Pandey
źródło
0

Hiberante obsługuje funkcję leniwej inicjalizacji zarówno dla jednostek, jak i kolekcji. Silnik hibernacji ładuje tylko te obiekty, o które pytamy, a nie inne elementy lub kolekcje.

lazy = "false" domyślnie ładowanie inicjalizacji wzmianka o jedynym dziecku jest leniwa. przypadek true oznacza, że ​​ładuje się rodzic nie obsługuje dziecka

abburi
źródło
0

Ustawienie Lazy decyduje o tym, czy załadować obiekty podrzędne podczas ładowania obiektu nadrzędnego. Należy to zrobić, ustawiając odpowiedni plik odwzorowania hibernacji klasy nadrzędnej. .

Manikandan Adhimoolam
źródło
0

Zaskakujące jest, że żadna z odpowiedzi nie mówi o tym, jak można to osiągnąć przez hibernację za ekranami.

Leniwe ładowanie to wzorzec projektowy, który jest skutecznie używany w hibernacji ze względu na wydajność, który obejmuje następujące techniki.


1. Instrumentacja kodu bajtowego :

Rozszerza definicję klasy bazowej za pomocą haków hibernacji do przecięcia wszystkie połączenia do tego obiektu podmiotu.

Sporządzono w czasie kompilacji lub w czasie [ładowania]

1.1 Czas kompilacji

  • Operacja po kompilacji

  • Głównie przez wtyczki maven / ant

1.2 Czas pracy

  • Jeśli nie wykonano instrumentacji w czasie kompilacji, jest ona tworzona w czasie wykonywania przy użyciu bibliotek, takich jak javassist

2. Proxy

Obiekt encji, który zwraca Hibernate, jest proxy typu rzeczywistego.

Zobacz także: Javassist. Jaka jest główna idea i gdzie realne zastosowanie?

Sankarganesh Eswaran
źródło