Domyślny typ pobierania dla jeden do jednego, wiele do jednego i jeden do wielu w trybie hibernacji

104

Jaki jest domyślny typ pobierania w odwzorowaniach w trybie hibernacji?

Po eksploracji dowiedziałem się:

  • dla jednego do jednego jest chętny .
  • dla jednego do wielu jest leniwy .

Ale po przetestowaniu go w Eclipse był chętny do wszystkiego.

Czy to zależy od tego, czy używam JPA czy hibernacji?

Richa
źródło
1
Jeśli nadal jesteś zaangażowany w tematy JPA - zaktualizowałem twoje pytanie o nową odpowiedź, ponieważ stare są nieaktualne w obecnej wersji Hibernacji.
Alexander Rühl

Odpowiedzi:

194

To zależy od tego, czy używasz JPA czy Hibernacji.

Ze specyfikacji JPA 2.0 wartości domyślne to:

OneToMany: LAZY
ManyToOne: EAGER
ManyToMany: LAZY
OneToOne: EAGER

A w stanie hibernacji wszystko jest leniwe

AKTUALIZACJA:

Najnowsza wersja Hibernate jest zgodna z powyższymi domyślnymi ustawieniami JPA.

Ashish Agarwal
źródło
11
„A w hibernacji wszystko jest leniwe” najwyraźniej zmieniło się w ostatnich wersjach. Zobacz odpowiedź Alexandra Rühla poniżej .
Dinei
1
Hibernate jest jedną z implementacji JPA, więc kiedy używasz Hibernate, używasz JPA :)
xenteros
To popularne zapytanie. @Ashish Agarwal Czy możesz zaktualizować ostatnią linię swojej odpowiedzi. W Hibernate nie jest teraz leniwy.
Saurabh Tiwari
Zaktualizowano post w odniesieniu do ostatniego zachowania Hibernacji.
M Anouti
Nastąpiła aktualizacja, która twierdziła, że ​​chętny jest domyślnym typem pobierania dla każdego mapowania, który został obalony w rozdziale 11.3 zarówno w obecnej wersji 5.x, jak i nowej 6.x dokumentacji Hibernate, więc cofnąłem edycję. Poza tym jest to sprzeczne z zaleceniem, aby nie mieć automatycznej chęci, ponieważ oznaczałoby to prawdopodobnie wybranie całej bazy danych podczas pobierania pojedynczego obiektu.
Alexander Rühl
52

Wiem, że odpowiedzi były poprawne w momencie zadawania pytania - ale ponieważ ludzie (tacy jak ja w tej chwili) wciąż zastanawiają się, dlaczego ich WildFly 10 zachowywał się inaczej, chciałbym podać aktualizację dla obecnego Hibernate 5 wersja .x:

W Podręczniku użytkownika Hibernate 5.2 jest to opisane w rozdziale 11.2. Stosowanie strategii pobierania :

Zalecenie Hibernate'a polega na statycznym oznaczaniu wszystkich skojarzeń jako leniwych i stosowaniu dynamicznych strategii pobierania w celu uzyskania chęci. Jest to niestety sprzeczne ze specyfikacją JPA, która określa, że wszystkie powiązania typu jeden do jednego i wiele do jednego powinny być domyślnie pobierane chętnie . Hibernate, jako dostawca JPA, honoruje to domyślne.

Zatem Hibernate również zachowuje się tak, jak wspomniany powyżej Ashish Agarwal dla JPA:

OneToMany: LAZY
ManyToOne: EAGER
ManyToMany: LAZY
OneToOne: EAGER

(patrz specyfikacja JPA 2.1 )

Alexander Rühl
źródło
A jeśli użyjemy natywnej hibernacji zamiast JPA impl, czy zachowuje się w ten sam sposób?
jMounir
@jMounir: Cóż, nie próbowałem tego, ale ponieważ Hibernate stwierdza, że ​​zachowuje się tak, jak zdefiniowano w JPA, nie rozumiem, dlaczego miałoby się to różnić, gdy używam Hibernate'a dla siebie. W obu przypadkach można pominąć domyślną strategię.
Alexander Rühl
15

Odpowiadając na twoje pytanie, Hibernate jest implementacją standardu JPA. Hibernate ma swoje własne dziwactwa, ale zgodnie z dokumentacją Hibernate

Domyślnie Hibernate używa pobierania z opóźnionym wyborem dla kolekcji i pobierania z opóźnieniem proxy dla asocjacji jednowartościowych. Te wartości domyślne mają sens w przypadku większości skojarzeń w większości aplikacji.

Zatem Hibernate zawsze ładuje dowolny obiekt przy użyciu leniwej strategii pobierania, bez względu na typ zadeklarowanej relacji. Użyje leniwego serwera proxy (który powinien być niezainicjowany, ale nie zerowy) dla pojedynczego obiektu w relacji jeden do jednego lub wiele do jednego oraz pustej kolekcji, którą nawadni wartościami, gdy spróbujesz uzyskać do niego dostęp .

Należy rozumieć, że Hibernate będzie usiłował wypełnić te obiekty wartościami tylko wtedy, gdy spróbujesz uzyskać dostęp do obiektu, chyba że określisz to fetchType.EAGER.

JamesENL
źródło
0

W przypadku asocjacji o pojedynczej wartości, tj.-Jeden do jednego i Wiele do jednego: -
Domyślnie Lazy = proxy Leniwe
ładowanie proxy : - Oznacza to, że ładowany jest obiekt proxy powiązanej jednostki. Oznacza to, że tylko identyfikator łączący dwie jednostki jest ładowany dla obiektu proxy powiązanej jednostki.
Np .: A i B to dwa byty ze skojarzeniem Wiele do jednego. tj .: może istnieć wiele A dla każdego B. Każdy obiekt A będzie zawierał odniesienie do B.
"

public class A{
    int aid;
    //some other A parameters;
    B b;
}
public class B{
    int bid;
     //some other B parameters;
}

`
Relacja A będzie zawierała kolumny (pomoc, oferta, ... inne kolumny podmiotu A).
Relacja B będzie zawierała kolumny (cena ofertowa, ... inne kolumny jednostki B).

Proxy oznacza, że ​​kiedy A jest pobierane, tylko id jest pobierane dla B i przechowywane w obiekcie proxy B, który zawiera tylko id. Obiekt proxy klasy B jest obiektem klasy proxy będącej podklasą klasy B z minimalną liczbą pól. Ponieważ oferta jest już częścią relacji A, nie jest konieczne uruchamianie zapytania w celu uzyskania oferty z relacji B. Inne atrybuty jednostki B są ładowane leniwie tylko wtedy, gdy jest otwierane pole inne niż oferta.

Dla kolekcji, tj.-Wiele-do-wielu i jeden-do-wielu: -
Domyślnie Lazy = true


Należy również pamiętać, że strategia pobierania (wybierz, dołącz itp.) Może zastąpić leniwość. tj .: Jeśli lazy = 'true' i fetch = 'join', pobranie A spowoduje również pobranie B lub Bs (w przypadku kolekcji). Możesz znaleźć powód, jeśli o tym pomyślisz.
Domyślne pobieranie dla asocjacji o pojedynczej wartości to „dołącz”.
Domyślne pobieranie dla kolekcji to „wybierz”. Sprawdź ostatnie dwie linie. Wydedukowałem to logicznie.

Jijo Mathew
źródło