Jestem nowicjuszem Java Persistence API i Hibernacji.
Jaka jest różnica między FetchType.LAZY
i FetchType.EAGER
w interfejsie API Java Persistence?
Jestem nowicjuszem Java Persistence API i Hibernacji.
Jaka jest różnica między FetchType.LAZY
i FetchType.EAGER
w interfejsie API Java Persistence?
Odpowiedzi:
Czasami masz dwa byty i istnieje między nimi związek. Na przykład możesz mieć jednostkę o nazwie,
University
a inna jednostka o nazwie,Student
a uniwersytet może mieć wielu studentów:Jednostka uniwersytecka może mieć pewne podstawowe właściwości, takie jak identyfikator, nazwa, adres itp., A także właściwość kolekcji zwaną studentami, która zwraca listę studentów dla danej uczelni:
Teraz, gdy ładujesz uniwersytet z bazy danych, JPA ładuje dla ciebie pola identyfikatora, nazwy i adresu. Ale masz dwie opcje dotyczące sposobu ładowania uczniów:
getStudents()
metodę uniwersytecką .Gdy uniwersytet ma wielu studentów, nie jest efektywnie ładować wszystkich studentów razem z nim, szczególnie gdy nie są oni potrzebni, aw takich przypadkach możesz zadeklarować, że chcesz, aby studenci zostali załadowani, gdy są faktycznie potrzebni. Nazywa się to leniwym ładowaniem.
Oto przykład, w którym
students
jest wyraźnie zaznaczony do szybkiego załadowania:A oto przykład, w którym
students
jest wyraźnie zaznaczony do załadowania leniwie:źródło
getStudents()
), Ale czasami nie jest to możliwe, ponieważ do czasu tej metody jest wywoływana, sesja jest już zamknięta, a jednostka odłączona. Podobnie, czasami mamy architekturę klient / serwer (np. Klient Swing / serwer JEE), a podmioty / DTO są przesyłane przewodowo do klienta i ponownie najczęściej w tych scenariuszach leniwe ładowanie nie będzie działać ze względu na sposób, w jaki podmioty są serializowane za pomocą drutu.getStudents()
metodę po raz pierwszy, wyniki są buforowane? aby następnym razem uzyskać szybszy dostęp do tych wyników?Gruntownie,
źródło
EAGER
ładowanie kolekcji oznacza, że są one pobierane w całości w momencie pobierania ich rodzica. Więc jeśli maszCourse
i takList<Student>
, wszyscy studenci są pobierani z bazy danych w momencieCourse
pobierania.LAZY
z drugiej strony oznacza, że zawartośćList
jest pobierana tylko wtedy, gdy próbujesz uzyskać do nich dostęp. Na przykład dzwoniąccourse.getStudents().iterator()
. Wywołanie dowolnej metody dostępuList
zainicjuje wywołanie bazy danych w celu pobrania elementów. Jest to realizowane przez utworzenie proxy wokółList
(lubSet
). Tak więc dla twoich leniwych kolekcji konkretne typy nie sąArrayList
iHashSet
, alePersistentSet
iPersistentList
(lubPersistentBag
)źródło
course.getStudents()
, uruchamia zapytanie SQL (widziałem to na konsoli). W typie pobierania Lazy również dzieje się to samo. Więc jaka jest różnica?fetchtype = LAZY
domyślny, nawet jeśli spróbujesz pobrać kolekcję za pomocą gettera hibernety zgłasza błąd informujący, że nie może ocenićMogę rozważyć wydajność i wykorzystanie pamięci. Jedną dużą różnicą jest to, że strategia pobierania EAGER pozwala na użycie pobranego obiektu danych bez sesji. Dlaczego?
Wszystkie dane są pobierane, gdy chętnie zaznaczone dane w obiekcie, gdy sesja jest połączona. Jednak w przypadku leniwej strategii ładowania, leniwe ładowanie zaznaczonego obiektu nie pobiera danych, jeśli sesja zostanie rozłączona (po
session.close()
instrukcji). Wszystko, co można zrobić przez hibernację proxy. Szybka strategia pozwala, aby dane były nadal dostępne po sesji zamknięcia.źródło
Zgodnie z moją wiedzą oba rodzaje pobierania zależą od wymagań.
FetchType.LAZY
jest na żądanie (tj. kiedy potrzebowaliśmy danych).FetchType.EAGER
jest natychmiastowy (tzn. zanim nadejdzie nasz wymóg, niepotrzebnie pobieramy rekord)źródło
Domyślnie dla wszystkich obiektów kolekcji i map obowiązuje reguła pobierania,
FetchType.LAZY
aw innych przypadkach jest zgodna zFetchType.EAGER
zasadami.W skrócie,
@OneToMany
a@ManyToMany
stosunki nie sprowadzić powiązanych obiektów (zbieranie i map) implicictly ale odzyskiwanie operacja jest kaskadowo przez pola w@OneToOne
i@ManyToOne
te.(dzięki uprzejmości: - objectdbcom)
źródło
Oba
FetchType.LAZY
iFetchType.EAGER
służą do zdefiniowania domyślnego planu pobierania .Niestety możesz zastąpić tylko domyślny plan pobierania dla LAZY pobierania. Pobieranie EAGER jest mniej elastyczne i może prowadzić do wielu problemów z wydajnością .
Radzę powstrzymać potrzebę tworzenia stowarzyszeń EAGER, ponieważ pobieranie jest obowiązkiem czasu zapytania. Dlatego wszystkie zapytania powinny korzystać z dyrektywy pobierania, aby pobrać tylko to, co jest konieczne w bieżącym uzasadnieniu biznesowym.
źródło
Z Javadoc :
Np. Chętny jest bardziej proaktywny niż leniwy. Leniwy zdarza się tylko przy pierwszym użyciu (jeśli dostawca skorzysta z podpowiedzi), podczas gdy z niecierpliwymi rzeczami (może) zostać wstępnie pobrany.
źródło
Typ
Lazy
pobierania jest domyślnie wybierany przez Hibernacja, chyba że wyraźnie zaznaczyszEager
typ pobierania. Aby być bardziej dokładnym i zwięzłym, różnicę można określić jak poniżej.FetchType.LAZY
= To nie ładuje relacji, chyba że wywołasz je metodą gettera.FetchType.EAGER
= To ładuje wszystkie relacje.Plusy i minusy tych dwóch typów pobierania.
Lazy initialization
poprawia wydajność, unikając niepotrzebnych obliczeń i zmniejszając wymagania dotyczące pamięci.Eager initialization
zajmuje więcej pamięci, a szybkość przetwarzania jest niska.To powiedziawszy, zależy od sytuacji, w której można zastosować jedną z tych inicjalizacji.
źródło
getMember
będzie dokładnie pasować do wzorca nazwy członka?Book.java
Subject.java
HibernateUtil.java
Main.java
Sprawdź metodę retrieve () w Main.java. Kiedy otrzymamy Temat, jego lista kolekcji Książki , opatrzone adnotacjami
@OneToMany
, zostaną załadowane leniwie. Ale z drugiej strony, Książki podobne stowarzyszenie odbioru przedmiotu , z uwagami@ManyToOne
, ładunki eargerly (autorem jest[default][1]
za@ManyToOne
,fetchType=EAGER
). Możemy zmienić zachowanie, umieszczając fetchType.EAGER na@OneToMany
Subject.java lub fetchType.LAZY na@ManyToOne
Books.java.źródło
Źródło
źródło
Chcę dodać tę notatkę do tego, co powiedział „Kyung Hwan Min” powyżej.
Załóżmy, że używasz Spring Rest z tym prostym architektem:
I chcesz zwrócić niektóre dane do interfejsu, jeśli używasz
FetchType.LAZY
, otrzymasz wyjątek po zwróceniu danych do metody kontrolera, ponieważ sesja jest zamknięta w usłudze, więcJSON Mapper Object
nie można uzyskać danych.Istnieją trzy typowe opcje rozwiązania tego problemu, w zależności od projektu, wydajności i dewelopera:
FetchType.EAGER
, aby sesja nadal żyła metodą kontrolera.FetchType.LAZY
metody konwertera do przesyłania danych zEntity
innego obiektu danychDTO
i wysyłania go do kontrolera, więc nie ma wyjątku, jeśli sesja zostanie zamknięta.źródło
Cześć, Dołączyłem 2 zdjęcia, które pomogą Ci to zrozumieć.
źródło
@ drop-shadow, jeśli używasz Hibernacji, możesz wywoływać
Hibernate.initialize()
po wywołaniugetStudents()
metody:źródło
LAZY: Leniwie pobiera encje potomne, tzn. W momencie pobierania encji nadrzędnej pobiera tylko proxy (utworzone przez cglib lub dowolne inne narzędzie) encji potomnych, a kiedy uzyskujesz dostęp do dowolnej właściwości encji podrzędnej, jest ona faktycznie pobierana przez hibernację.
EAGER: pobiera byty potomne wraz z rodzicem.
Aby lepiej zrozumieć, przejdź do dokumentacji Jboss lub możesz użyć
hibernate.show_sql=true
aplikacji i sprawdzić zapytania wygenerowane przez hibernację.źródło