Jakie jest zastosowanie session.flush () w Hibernate

110

Kiedy aktualizujemy rekord, możemy użyć session.flush()z Hibernate. Jaka jest potrzeba flush()?

CHANTI
źródło

Odpowiedzi:

138

Opróżnianie sesji wymusza na Hibernate synchronizację stanu pamięci Sessionz bazą danych (tj. Zapis zmian w bazie danych). Domyślnie Hibernacja automatycznie opróżni zmiany:

  • przed niektórymi wykonaniami zapytań
  • kiedy transakcja zostaje zatwierdzona

Zezwolenie na jawne opróżnienie Sessiondaje dokładniejszą kontrolę, która może być wymagana w niektórych okolicznościach (aby uzyskać przypisany identyfikator, kontrolować rozmiar sesji, ...).

Pascal Thivent
źródło
8
Zauważ, że ta odpowiedź opisuje DOMYŚLNE zachowanie hibernacji: zachowanie opróżniania można zmienić za pomocą ustawienia Flush Mode. Szczegóły znajdują się w docs.jboss.org/hibernate/orm/3.5/api/org/hibernate/… (wersja 3.5).
SteveT,
1
Znalazłem dokument, w którym jest powiedziane dokładnie to, co mówisz, ale mam pytanie, że co będzie priorytetem oznacza załóżmy 1) Mam klasę, w której zapisuję obiekt za pomocą kodu id = session.save(obj);i transakcja jest zatwierdzana w następnej linii, ale obj nie jest zapisywana do DB, dlaczego? 2) Zapisałem obj używając session.save(obj);z zatwierdzeniem i podczas powrotu użyłem return obj.getprimaryID();W tym przypadku obj jest zapisywany w DB. Dlaczego więc tak się dzieje?
Amogh
74

Jak słusznie powiedzieliśmy w powyższych odpowiedziach, dzwoniąc flush() wymusza hibernację w celu wykonania poleceń SQL w bazie danych. Ale zrozum, że zmiany nie są jeszcze „zatwierdzone”. Więc po wykonaniu flush i przed zatwierdzeniem, jeśli uzyskasz bezpośredni dostęp do DB (powiedzmy z zachęty SQL) i sprawdzisz zmodyfikowane wiersze, NIE zobaczysz zmian.

To samo, co otwarcie 2 sesji poleceń SQL. A zmiany dokonane w jednej sesji nie są widoczne dla innych, dopóki nie zostaną zatwierdzone.

Kaushik Lele
źródło
12
No cóż - zmiany mogą być lekko widoczne. Na przykład niezatwierdzony wiersz może utworzyć blokadę we wstawionym, ale niezatwierdzonym wierszu i opóźnić wstawienie tego samego wiersza przez inną sesję do momentu zatwierdzenia lub wycofania transakcji. Nie jest więc całkowicie niewidoczne.
rghome
2
Surfowałem po całej sieci i to jest odpowiedź, która w końcu sprawiła, że ​​ją dostałem. Dzięki.
Siddhartha
Jaki jest pożytek z umieszczenia .flush () w pętli for, a jeśli commit () wykona flush na końcu?
Eildosa
@Kaushik Lele Po co flush (), jeśli dane nie są widoczne po flush? Czy możesz rozwinąć niektóre z drobniejszych przypadków użycia, w których jest to przydatne?
java_geek
28

Wiem tylko, że kiedy wywołujemy, session.flush()nasze instrukcje są wykonywane w bazie danych, ale nie są zatwierdzane.

Załóżmy, że nie wywołujemy flush()metody na obiekcie sesji i jeśli wywołamy metodę commit, to wewnętrznie wykona ona pracę polegającą na wykonaniu instrukcji w bazie danych, a następnie zatwierdzeniu.

commit=flush+commit (w przypadku funkcjonalności)

Dlatego dochodzę do wniosku, że kiedy wywołujemy metodę flush () na obiekcie Session, to nie otrzymuje ona zatwierdzenia, ale trafia do bazy danych i wykonuje zapytanie, a także otrzymuje wycofanie.

W celu zatwierdzenia używamy funkcji commit () na obiekcie Transaction.

Shoaib Chikate
źródło
Czy możesz podać kilka szczegółów na temat potrzeby spłukiwania?
java_geek
14

Opróżnianie sesji powoduje, że dane, które są aktualnie w sesji, są zsynchronizowane z tym, co znajduje się w bazie danych.

Więcej na stronie Hibernate:

flush()jest przydatne, ponieważ nie ma absolutnie żadnej gwarancji, kiedy sesja wykona wywołania JDBC, tylko kolejność, w jakiej są wykonywane - z wyjątkiem tego, którego używasz flush().

miku
źródło
Czy możesz podać scenariusz, w którym użytkownik powinien martwić się o sekwencję? Użycie hibernacji ma na celu uczynienie rzeczy związanych z DB przezroczystymi dla użytkownika. Kiedy wykonujemy „zatwierdzenie”, opróżnianie następuje automatycznie. Jaki jest scenariusz, w którym zrobisz kolor, ale nie wykonasz zobowiązania?
Kaushik Lele
1
@KaushikLele, możesz odnieść się do tego pytania stackoverflow.com/questions/37382872/…
GMsoF
10

Możesz użyć flushdo wymuszenia realizacji i wykrycia ograniczeń walidacji w znanym miejscu, a nie wtedy, gdy transakcja zostanie zatwierdzona. Może się zdarzyć, że commitzostanie wywołany niejawnie przez jakąś logikę struktury, logikę deklaratywną, kontener lub szablon. W takim przypadku każdy zgłoszony wyjątek może być trudny do przechwycenia i obsługi (może być zbyt wysoki w kodzie).

Na przykład, jeśli masz save()nowy obiekt EmailAddress, który ma unikalne ograniczenie adresu, nie otrzymasz błędu, dopóki nie zatwierdzisz.

Wywołanie flush()wymusza wstawienie wiersza, zgłaszając wyjątek, jeśli istnieje duplikat.

Jednak po wystąpieniu wyjątku konieczne będzie wycofanie sesji.

rghome
źródło
4

Chciałbym tylko zebrać wszystkie odpowiedzi podane powyżej, a także powiązać metodę Flush () z Session.save (), aby nadać większe znaczenie

Hibernate save () można użyć do zapisania jednostki do bazy danych. Możemy wywołać tę metodę poza transakcją, dlatego nie podoba mi się ta metoda zapisywania danych. Jeśli używamy tego bez transakcji i mamy kaskadowanie między jednostkami, to tylko jednostka podstawowa zostanie zapisana, chyba że opróżnimy sesję.

flush (): wymusza flush sesji. Służy do synchronizacji danych sesji z bazą danych.

Kiedy wywołujesz session.flush (), instrukcje są wykonywane w bazie danych, ale nie zostaną zatwierdzone. Jeśli nie wywołasz session.flush () i jeśli wywołasz session.commit (), to wewnętrznie metoda commit () wykonuje instrukcję i zatwierdza.

Więc commit () = flush + commit. Tak więc session.flush () po prostu wykonuje instrukcje w bazie danych (ale nie zatwierdza), a instrukcje NIE SĄ już W PAMIĘCI. Po prostu zmusza sesję do spłukiwania.

Kilka ważnych punktów:

Powinniśmy unikać zapisywania poza granicami transakcji, w przeciwnym razie zmapowane jednostki nie zostaną zapisane, powodując niespójność danych. Zapominanie o opróżnianiu sesji jest bardzo normalne, ponieważ nie powoduje to żadnych wyjątków ani ostrzeżeń. Domyślnie Hibernate automatycznie opróżni zmiany: przed wykonaniem niektórych zapytań po zatwierdzeniu transakcji Zezwolenie na jawne opróżnienie Sesji daje dokładniejszą kontrolę, która może być wymagana w pewnych okolicznościach (aby uzyskać przypisany identyfikator, aby kontrolować rozmiar sesji )

Sundar Gsv
źródło
3

flush() Metoda powoduje Hibernate do spłukiwania sesję. Możesz skonfigurować hibernację, aby używała trybu opróżniania sesji przy użyciu setFlushMode()metody. Aby uzyskać tryb flush dla bieżącej sesji, możesz użyć getFlushMode()metody. Aby sprawdzić, czy sesja jest brudna, możesz użyć isDirty()metody. Domyślnie Hibernate zarządza opróżnianiem sesji.

Jak podano w dokumentacji:

https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/chapters/flushing/Flushing.html

Płukanie

Opróżnianie to proces synchronizowania stanu kontekstu trwałości z bazową bazą danych. EntityManagerI Hibernate Sessionodsłonić zestaw metod, dzięki którym programista aplikacji może zmienić uporczywy stan jednostki.

Kontekst trwałości działa jako transakcyjna pamięć podręczna z zapisem, umieszczając w kolejce każdą zmianę stanu jednostki. Podobnie jak w przypadku każdej pamięci podręcznej z zapisem, zmiany są najpierw wprowadzane do pamięci i synchronizowane z bazą danych w czasie opróżniania. Operacja trwa równo każdą zmianę stanu encji i przekłada go do INSERT, UPDATElub DELETEoświadczenia.

Strategia opróżniania jest podawana przez tryb flushMode bieżącej sesji Hibernate. Chociaż JPA definiuje tylko dwie strategie spłukiwania ( AUTOi COMMIT), Hibernate ma znacznie szersze spektrum typów spłukiwania:

  • ALWAYS: Opróżnia sesję przed każdym zapytaniem;
  • AUTO: Jest to tryb domyślny i opróżnia sesję tylko w razie potrzeby;
  • COMMIT: Sesja próbuje opóźnić kolor do momentu zatwierdzenia bieżącej Transakcji, chociaż może również przedwcześnie opróżnić;
  • MANUAL: Opróżnianie sesji jest delegowane do aplikacji, która musi wywołać Session.flush()jawnie, aby zastosować zmiany kontekstu trwałości.

Domyślnie Hibernate używa AUTOtrybu flush, który wyzwala flush w następujących okolicznościach:

  • przed dokonaniem Transakcji;
  • przed wykonaniem zapytania JPQL / HQL, które nakłada się na akcje jednostki w kolejce;
  • przed wykonaniem jakiegokolwiek natywnego zapytania SQL, które nie ma zarejestrowanej synchronizacji.

źródło
1

Dzwonienie EntityManager#flushma skutki uboczne . Jest wygodnie używany w przypadku typów jednostek z wygenerowanymi wartościami identyfikatora (wartości sekwencji): taki identyfikator jest dostępny tylko po synchronizacji z podstawową warstwą trwałości. Jeśli ten identyfikator jest wymagany przed zakończeniem bieżącej transakcji (na przykład do celów logowania), wymagane jest opróżnienie sesji.

johanwannheden
źródło
0

Dzięki tej metodzie wywołujesz proces spłukiwania. Ten proces synchronizuje stan bazy danych ze stanem sesji, wykrywając zmiany stanu i wykonując odpowiednie instrukcje SQL.

lennoxGER
źródło