JPA - metoda flush();

JPA - metoda flush();
P1
  • Rejestracja:ponad 14 lat
  • Ostatnio:ponad 12 lat
  • Postów:150
2

Z tego co zrozumiał z dokumentacji metoda flush() wywołana w transakcji ignoruje (obchodzi) jakby transakcje i powoduje przekazanie stanu obiektów encji do bazy danych bez czekania na polecenie commit() dla tej transakcji. Mam pytanie czy to spłukanie "flush'em" to jest już pełne zatwierdzenie zmian w bazie ? Czy jeżeli po flush'u nastąpi rollback transakcji to zmiany dokonane przez flush zostaną cofnięte czy też są już commitowane i pozostaną w bazie?

Z tego co jeszcze wywnioskowałem (a chciałbym potwierdzić) to to że metody detach() i clear() działają również natychmiast pomimo że są wywoływane w transakcji. To znaczy że obiekt encji jest odrywany od Contextu w momencie wywołania tych metod, bez czekania na operację commit() i już nie "manged" w dalszym ciągu transakcji. Czy taka sama natychmiastowa reakcja ignorująca transakcje zachodzi dla wywołań pozostałych metod kaskadowych: merge, remove, refresh?

Wibowit
  • Rejestracja:około 20 lat
  • Ostatnio:mniej niż minuta
0

Ja się dołączam do pytania i dodatkowo chciałbym się dowiedzieć czy pod Hibernatem jest tak samo? Tzn przy samodzielnym Hibernacie, a nie jako dostawcy JPA.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
__krzysiek85
  • Rejestracja:ponad 18 lat
  • Ostatnio:ponad 9 lat
  • Postów:1019
1

Załóżmy, że mamy metodę z adnotacją @Transactional (gdy Spring zarządza transakcjami) lub metodę ejb z CMT.

Standardowy flow wygląda następująco.

  1. Na wejściu do metody tworzona jest transakcja.
  2. W trakcie metody są wykonywane różne operacje na encjach. Hibernate może sam zadecydować w trakcie metody, że część zmian trzeba wrzucić do bazy (domyślnie FlushMode jest ustawiony na AUTO, więcej: http://docs.jboss.org/hibernate/orm/3.5/api/org/hibernate/FlushMode.html)
  3. Na koniec metody wrzucane są pozostałe zmiany.
  4. Transakcja jest commitowana.

Dodanie flush() wymusza wrzucenie zmian do bazy, ale jeszce nie commituje transakcji.
Od tej chwili zmiany są widoczne dla innych transakcji odczytujących dane z poziomem izolacji read uncommitted.
Jeżeli po flush() nastąpi rollback, to wszystkie zmiany zostaną wycofane.

Kiedy przydaje się flush:
-w jednej sesji zmieniamy bardzo dużo obiektów. Aby uniknąć problemów z pamięcią należy w paczkach po np. 200 encji wykonywać zmiany i później wykonywać flush() i następnie clear().
-w jednej sesji najpierw zmieniamy stan w obiekcie, a później w tej samej sesji wywołujemy zapytanie jdbc/procedurę, która korzysta z tych danych. Oczywiście, aby to zapytanie/procedura mogła widzieć dane, muszą one być w bazie. Zapytanie/procedura działa w tej samej transakcji, więc będzie widzieć dane bez potrzeby zmiany poziomu izolacji

Ja się dołączam do pytania i dodatkowo chciałbym się dowiedzieć czy pod Hibernatem jest tak samo? Tzn przy samodzielnym Hibernacie, a nie jako dostawcy JPA.

Nie ma tu znaczenia, czy korzystasz z Session, czy EntityManagera. Obie klasy zachowują się w tym przypadku tak samo.

Z tego co jeszcze wywnioskowałem (a chciałbym potwierdzić) to to że metody detach() i clear() działają również natychmiast pomimo że są wywoływane w transakcji. To znaczy że obiekt encji jest odrywany od Contextu w momencie wywołania tych metod, bez czekania na operację commit() i już nie "manged" w dalszym ciągu transakcji

http://docs.jboss.org/hibernate/orm/3.5/api/org/hibernate/Session.html#clear%28%29:

Completely clear the session. Evict all loaded instances and cancel all pending saves, updates and deletions. Do not close open iterators or instances of ScrollableResults.

Z tego powodu zawsze przed clear() należy wywoływać flush().
W rzeczywistości clear() przydaje się jedynie wtedy, gdy przetwarzamy wiele obiektów w pętli i co pewien czas musimy robić flush(); clear();


Registered Linux user #456405 | SCJP 6 | SCWCD 5 | SCBCD 5
edytowany 7x, ostatnio: __krzysiek85
Koziołek
Moderator
  • Rejestracja:około 18 lat
  • Ostatnio:minuta
  • Lokalizacja:Stacktrace
  • Postów:6822
1

Generalnie sqlki mogą być trzymane w pamięci podręcznej EM i będą fizycznie wysłane do bazy w momencie zatwierdzania transakcji po stronie JPA. Flush wymusza wysłanie zapamiętanej sqlki/sqlek do bazy, ale nie wysyła commit zatem nawet jak coś się zwali to zawsze można zrobić rollback. Jest oczywiście jedno ale... mianowicie jeżeli wywołasz flush, następnie zrobisz rollback to nie zostaną cofnięte zmiany w sekwencjach, auto-id i tym podobnych duperelach.


Sięgam tam, gdzie wzrok nie sięga… a tam NullPointerException
P1
  • Rejestracja:ponad 14 lat
  • Ostatnio:ponad 12 lat
  • Postów:150
0

Dzięki wielkie za wyjaśnienie.

Koziołek

następnie zrobisz rollback to nie zostaną cofnięte zmiany w sekwencjach, auto-id i tym podobnych duperelach.

auto-id - rozumiem że to automatyczne nadawanie numeracji w bazie dla kolejnego rekordu, czyli ten numer po rollbacku się nie wycofa z bazy razem z rekordem. Przy kolejnym dodawaniu kolejne rekordy wejdą do bazy z następnymi numerami i w bazie będzie skok numeracyjny o jedną pozycję czy tak?
Czy może chodzi o pole Primary key (auto-id) czyli numer @GeneratedValue(strategy = GenerationType.AUTO) jaki pobierze sobie obiekt encji przy jego flush'owaniu do bazy i to ten numer w tej encji nie zostanie cofnięty?

Powtórzę jeszcze tylko pytanko o te metody merge, remove, refresh - tez mają taka natychmiastową wykonalność we wnętrzu trwającej transakcji? Czy obiekt encji jest natychmiast mergowany do Conextu albo refreshowany z bazy bez czekania na commit?
Remove podobno oznacza tylko encje do usunięcia a usuwane są dopiero przy commicie.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.