Różnica między JOIN I JOIN FETCH w Hibernate

Proszę, pomóż mi zrozumieć, gdzie używać zwykłego JOIN i gdzie JOIN FETCH.

Na przykład, jeśli mamy te dwa zapytania

FROM Employee emp
JOIN emp.department dep

I

FROM Employee emp
JOIN FETCH emp.department dep
Czy jest między nimi jakaś różnica? Jeśli tak, to którego z nich użyć kiedy?
Author: abbas, 2013-07-02

4 answers

W tych dwóch zapytaniach, używasz JOIN do odpytywania wszystkich pracowników, którzy mają co najmniej jeden dział powiązany.

Ale różnica jest taka: w pierwszym zapytaniu zwracasz tylko pracowników dla Hibernate. W drugim zapytaniu zwracasz pracowników i wszystkich powiązanych działów.

Tak więc, jeśli użyjesz drugiego zapytania, nie będziesz musiał wykonywać nowego zapytania, aby ponownie trafić do bazy danych, aby zobaczyć działy każdego pracownika.

Możesz użyć drugie pytanie, gdy masz pewność, że będziesz potrzebował działu każdego pracownika. Jeśli nie potrzebujesz działu, użyj pierwszego zapytania.

Polecam przeczytać ten link, jeśli potrzebujesz zastosować warunek WHERE (co prawdopodobnie będzie potrzebne): Jak poprawnie wyrazić JPQL" join fetch "z klauzulą" where"jako kryterium JPA 2?

Update

Jeśli nie korzystasz z fetch, a działy nadal są zwracane, to dlatego, że mapowanie między pracownikiem a Dział (a @OneToMany) jest ustawiany przez FetchType.EAGER. W tym przypadku, każde zapytanie HQL (z fetch lub nie) z FROM Employee przyniesie wszystkie działy. Pamiętaj, że wszystkie mapowania *ToOne (@ManyToOne i @OneToOne) są domyślnie pożądane.

 116
Author: Dherik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:47

W ten link wspomniałem wcześniej w komentarzu, przeczytaj tę część:

Złącze "fetch" pozwala na Asocjacje lub zbiory wartości inicjowane wraz z obiektami nadrzędnymi za pomocą jednego wyboru. Jest to szczególnie przydatne w przypadku kolekcji. It skutecznie zastępuje zewnętrzne join i leniwe deklaracje plik mapowania dla asocjacji i zbiorów.

Ten "JOIN FETCH" będzie miał swój efekt, jeśli masz (fetch = FetchType.Lazy) właściwość dla kolekcji wewnątrz encji(przykład poniżej).

I jest to tylko efekt metody "kiedy zapytanie powinno się zdarzyć". I musisz też wiedzieć to :

Hibernate mają dwa ortogonalne pojęcia : kiedy jest pobierane skojarzenie i jak jest na wyciągnięcie. Ważne jest, aby ich nie mylić. Używamy Pobierz, aby dostroić wydajność. Możemy użyć lazy do określenia umowy dla jakie dane są zawsze dostępne w każdej odłączonej instancji w szczególności klasy.

Kiedy zostanie pobrane skojarzenie -- > Twój typ "FETCH"

Jak to jest pobierane -- > Join / select/Subselect / Batch

W Twoim przypadku FETCH będzie miał swój efekt tylko wtedy, gdy masz dział jako zbiór wewnątrz pracownika, coś takiego w encji:

@OneToMany(fetch = FetchType.LAZY)
private Set<Department> department;

Kiedy używasz

FROM Employee emp
JOIN FETCH emp.department dep

Otrzymasz emp i emp.dep. gdy nie używasz fetch, możesz nadal uzyskać emp.dep, ale hibernate przetworzy inny select do bazy danych, aby uzyskać ten dział.

Więc to tylko kwestia dostrojenia wydajności, o tym, że chcesz uzyskać wszystkie wyniki (potrzebujesz tego lub nie) w jednym zapytaniu( eager fetching), lub chcesz go odpytywać, gdy tego potrzebujesz(lazy fetching).

Użyj eager fetching, gdy chcesz uzyskać małe dane za pomocą jednego select (jedno duże zapytanie). Lub użyj leniwego pobierania, aby odpytywać to,czego potrzebujesz (wiele mniejszych zapytań).

Użyj fetch gdy:

  • No large unneeded collection / set wewnątrz tej istoty, którą zaraz dostaniesz

  • Komunikacja z serwera aplikacji do serwera bazy danych zbyt daleko i wymaga długiego czasu

  • Możesz potrzebować tej kolekcji, gdy nie masz do niej dostępu (poza metody/klasy transactional)

 50
Author: Angga,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-16 02:17:55

Jeśli masz ustawione mapowanie @ oneToOne na FetchType.Leniwy i używasz drugiego zapytania (ponieważ musisz ładować Obiekty działu jako część obiektów pracownika) co zrobi Hibernate, będzie wysyłać zapytania do pobierania obiektów działu Dla każdego pojedynczego obiektu pracownika, który pobiera z DB. Później w kodzie można uzyskać dostęp do obiektów Departamentu poprzez Employee to Department Asocjacja jednowartościowa i Hibernate nie wystawi żadnego zapytania do fetch Department object dla danego pracownika. Pamiętaj, Hibernate nadal wysyła zapytania równe liczbie pracowników, których pobrał. Hibernate wyda taką samą liczbę zapytań w obu powyższych zapytaniach, jeśli chcesz uzyskać dostęp do obiektów działu wszystkich obiektów pracowników

 4
Author: Bunti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-14 22:51:06

Dherik: nie jestem pewien, co mówisz, gdy nie używasz fetch, wynik będzie typu: List<Object[ ]>, co oznacza listę tabel obiektów, a nie listę pracowników.

Object[0] refers an Employee entity 
Object[1] refers a Departement entity 

Gdy używasz fetch, jest tylko jeden select, a wynikiem jest lista pracowników List<Employee> zawierająca listę departamentów. Nadpisuje leniwą deklarację podmiotu.

 2
Author: Bilal BBB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-21 18:52:44