Odpowiedzi:
Opróżnianie sesji wymusza na Hibernate synchronizację stanu pamięci Session
z bazą danych (tj. Zapis zmian w bazie danych). Domyślnie Hibernacja automatycznie opróżni zmiany:
Zezwolenie na jawne opróżnienie Session
daje dokładniejszą kontrolę, która może być wymagana w niektórych okolicznościach (aby uzyskać przypisany identyfikator, kontrolować rozmiar sesji, ...).
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?
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.
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.
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()
.
Możesz użyć flush
do wymuszenia realizacji i wykrycia ograniczeń walidacji w znanym miejscu, a nie wtedy, gdy transakcja zostanie zatwierdzona. Może się zdarzyć, że commit
zostanie 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.
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 )
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.
EntityManager
I HibernateSession
odsł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
,UPDATE
lubDELETE
oświadczenia.Strategia opróżniania jest podawana przez tryb flushMode bieżącej sesji Hibernate. Chociaż JPA definiuje tylko dwie strategie spłukiwania (
AUTO
iCOMMIT
), 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
AUTO
trybu 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.
Dzwonienie EntityManager#flush
ma 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.