Was ist die Verwendung von session.flush () im Ruhezustand?


110

Wenn wir einen Datensatz aktualisieren, können wir ihn session.flush()mit dem Ruhezustand verwenden. Was ist die Notwendigkeit flush()?

Antworten:


138

Durch das Leeren der Sitzung wird der Ruhezustand gezwungen, den speicherinternen Status von Sessionmit der Datenbank zu synchronisieren (dh Änderungen in die Datenbank zu schreiben). Standardmäßig löscht Hibernate Änderungen automatisch für Sie:

  • vor einigen Abfrageausführungen
  • wenn eine Transaktion festgeschrieben wird

Wenn Sie das explizite Löschen zulassen, erhalten Sie Sessioneine genauere Kontrolle, die unter bestimmten Umständen erforderlich sein kann (um eine ID zuzuweisen, um die Größe der Sitzung zu steuern, ...).


8
Beachten Sie, dass diese Antwort das DEFAULT Hibernate-Verhalten beschreibt: Das Flush-Verhalten kann über die Einstellung Flush Mode geändert werden. Details finden Sie in docs.jboss.org/hibernate/orm/3.5/api/org/hibernate/… (Version 3.5).
SteveT

1
Ich habe das Dokument gefunden, in dem genau das steht, was Sie sagen, aber ich habe die Frage, was Priorität bedeutet. Angenommen, 1) Ich habe eine Klasse, in der ich ein Objekt mit Code speichere id = session.save(obj);und die Transaktion in der nächsten Zeile festgeschrieben wird, aber obj wird nicht gespeichert an die DB, warum? 2) Ich habe obj session.save(obj);mit commit gespeichert und bei der Rückgabe verwendet. return obj.getprimaryID();In diesem Fall wird obj in der Datenbank gespeichert. Warum passiert dieses Verhalten?
Amogh

74

Wie in den obigen Antworten zu Recht gesagt, telefonisch flush() erzwingen wir Ruhezustand, um die SQL-Befehle in der Datenbank auszuführen. Aber verstehen Sie, dass Änderungen noch nicht "festgeschrieben" sind. Wenn Sie also nach dem Flush und vor dem Commit direkt auf die Datenbank zugreifen (z. B. über die SQL-Eingabeaufforderung) und die geänderten Zeilen überprüfen, werden die Änderungen NICHT angezeigt.

Dies entspricht dem Öffnen von 2 SQL-Befehlssitzungen. Und Änderungen, die in einer Sitzung vorgenommen wurden, sind für andere erst sichtbar, wenn sie festgeschrieben wurden.


12
Nun - die Änderungen können leicht sichtbar sein. Beispielsweise kann eine nicht festgeschriebene Zeile eine Sperre für die eingefügte, aber nicht festgeschriebene Zeile erstellen und das Einfügen derselben Zeile durch eine andere Sitzung verzögern, bis die Transaktion festgeschrieben oder zurückgesetzt wird. Es ist also nicht völlig unsichtbar.
rghome

2
Ich habe im ganzen Internet gesurft und dies ist die Antwort, die mich dazu gebracht hat, sie zu bekommen. Vielen Dank.
Siddhartha

Was nützt es, .flush () in eine for-Schleife zu setzen, wenn commit () am Ende einen Flush ausführt?
Eildosa

@Kaushik Lele Was ist der Sinn von Flush (), wenn die Daten nach Flush nicht sichtbar sind? Können Sie einige der feineren Anwendungsfälle erläutern, in denen dies nützlich ist?
java_geek

28

Ich weiß nur, dass session.flush()unsere Anweisungen beim Aufruf in der Datenbank ausgeführt, aber nicht festgeschrieben werden.

Angenommen, wir rufen keine flush()Methode für das Sitzungsobjekt auf, und wenn wir die Festschreibungsmethode aufrufen, werden intern Anweisungen in der Datenbank ausgeführt und anschließend festgeschrieben.

commit=flush+commit (bei Funktionalität)

Daher komme ich zu dem Schluss, dass beim Aufrufen der Methode flush () für das Sitzungsobjekt kein Commit ausgeführt wird, sondern die Datenbank erreicht und die Abfrage ausgeführt wird und auch ein Rollback ausgeführt wird.

Zum Festschreiben verwenden wir commit () für das Transaktionsobjekt.


Können Sie einige Details dazu angeben, was für eine Spülung erforderlich ist?
java_geek

14

Durch das Leeren der Sitzung werden die Daten, die sich derzeit in der Sitzung befinden, mit den Daten in der Datenbank synchronisiert.

Mehr auf der Hibernate-Website:

flush()Dies ist nützlich, da es absolut keine Garantie dafür gibt, wann die Sitzung die JDBC-Aufrufe ausführt, sondern nur die Reihenfolge, in der sie ausgeführt werden - außer Sie verwenden flush().


Können Sie ein Szenario angeben, in dem sich der Benutzer über die Reihenfolge Gedanken machen sollte? Die Verwendung des Ruhezustands dient dazu, DB-bezogene Dinge für den Benutzer transparent zu machen. Wenn wir "festschreiben", erfolgt das Spülen automatisch. In welchem ​​Szenario werden Sie spülen, aber nicht festschreiben?
Kaushik Lele

1
@ KaushikLele können Sie sich auf diese Frage stapeln stackoverflow.com/questions/37382872/…
GMsoF

10

Sie können verwenden, um flushzu erzwingen, dass Validierungsbeschränkungen an einem bekannten Ort realisiert und erkannt werden, anstatt wenn die Transaktion festgeschrieben wird. Es kann sein, dass dies commitimplizit von einer Framework-Logik, einer deklarativen Logik, dem Container oder einer Vorlage aufgerufen wird. In diesem Fall kann es schwierig sein, eine ausgelöste Ausnahme abzufangen und zu behandeln (sie kann im Code zu hoch sein).

Wenn Sie beispielsweise save()ein neues EmailAddress-Objekt verwenden, dessen Adresse eine eindeutige Einschränkung aufweist, wird erst beim Festschreiben eine Fehlermeldung angezeigt.

Beim Aufrufen flush()wird das Einfügen der Zeile erzwungen, und es wird eine Ausnahme ausgelöst, wenn ein Duplikat vorhanden ist.

Sie müssen die Sitzung jedoch nach der Ausnahme zurücksetzen.


4

Ich möchte nur alle oben gegebenen Antworten zusammenfassen und die Flush () -Methode mit Session.save () verknüpfen, um mehr Bedeutung zu verleihen

Hibernate save () kann verwendet werden, um die Entität in der Datenbank zu speichern. Wir können diese Methode außerhalb einer Transaktion aufrufen. Deshalb mag ich diese Methode nicht, um Daten zu speichern. Wenn wir dies ohne Transaktion verwenden und zwischen Entitäten kaskadieren, wird nur die primäre Entität gespeichert, es sei denn, wir leeren die Sitzung.

flush (): Erzwingt das Leeren der Sitzung. Es wird verwendet, um Sitzungsdaten mit der Datenbank zu synchronisieren.

Wenn Sie session.flush () aufrufen, werden die Anweisungen in der Datenbank ausgeführt, aber nicht festgeschrieben. Wenn Sie session.flush () nicht aufrufen und session.commit () aufrufen, führt die intern commit () -Methode die Anweisung aus und schreibt fest.

Also commit () = flush + commit. Session.flush () führt also nur die Anweisungen in der Datenbank aus (aber keine Commits) und Anweisungen sind NICHT MEHR IM SPEICHER. Es zwingt die Sitzung nur zum Spülen.

Einige wichtige Punkte:

Wir sollten das Speichern außerhalb der Transaktionsgrenze vermeiden, da sonst zugeordnete Entitäten nicht gespeichert werden, was zu Dateninkonsistenzen führt. Es ist ganz normal, das Leeren der Sitzung zu vergessen, da keine Ausnahmen oder Warnungen ausgegeben werden. Standardmäßig löscht Hibernate Änderungen automatisch für Sie: Vor einigen Abfrageausführungen, wenn eine Transaktion festgeschrieben wird. Wenn Sie die Sitzung explizit löschen, erhalten Sie eine genauere Kontrolle, die unter bestimmten Umständen erforderlich sein kann (um eine ID zuzuweisen, um die Größe der Sitzung zu steuern )


3

Die flush() Methode bewirkt, dass der Ruhezustand die Sitzung leert. Sie können den Ruhezustand mithilfe der setFlushMode()Methode so konfigurieren, dass der Spülmodus für die Sitzung verwendet wird. Um den Flush-Modus für die aktuelle Sitzung abzurufen, können Sie die getFlushMode()Methode verwenden. Um zu überprüfen, ob die Sitzung verschmutzt ist, können Sie die isDirty()Methode verwenden. Standardmäßig verwaltet Hibernate das Leeren der Sitzungen.

Wie in der Dokumentation angegeben:

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

Spülen

Beim Flushing wird der Status des Persistenzkontexts mit der zugrunde liegenden Datenbank synchronisiert. Der EntityManagerund der Ruhezustand Sessionstellen eine Reihe von Methoden bereit, mit denen der Anwendungsentwickler den persistenten Status einer Entität ändern kann.

Der Persistenzkontext fungiert als Transaktions-Write-Behind-Cache, der jede Änderung des Entitätsstatus in die Warteschlange stellt. Wie bei jedem Write-Behind-Cache werden Änderungen zuerst im Arbeitsspeicher angewendet und während der Flush-Zeit mit der Datenbank synchronisiert. Die Flush-Operation übernimmt jede Änderung des Entitätsstatus und übersetzt sie in ein INSERT, UPDATEoderDELETE Aussage.

Die Spülstrategie wird durch den FlushMode der aktuell ausgeführten Hibernate-Sitzung angegeben. Obwohl JPA nur zwei Spülstrategien ( AUTOund COMMIT) definiert, verfügt Hibernate über ein viel breiteres Spektrum an Spültypen:

  • ALWAYS: Leert die Sitzung vor jeder Abfrage.
  • AUTO: Dies ist der Standardmodus und löscht die Sitzung nur bei Bedarf.
  • COMMIT: Die Sitzung versucht, das Löschen zu verzögern, bis die aktuelle Transaktion festgeschrieben wird, obwohl sie möglicherweise auch vorzeitig gelöscht wird.
  • MANUAL: Die Sitzungsbereinigung wird an die Anwendung delegiert, die Session.flush()explizit aufgerufen werden muss, um die Änderungen des Persistenzkontexts anzuwenden.

Standardmäßig verwendet Hibernate den AUTOFlush-Modus, der unter folgenden Umständen einen Flush auslöst:

  • vor dem Festschreiben einer Transaktion;
  • vor dem Ausführen einer JPQL / HQL-Abfrage, die sich mit den Entitätsaktionen in der Warteschlange überschneidet;
  • bevor Sie eine native SQL-Abfrage ausführen, für die keine Synchronisierung registriert ist.

1

Anrufen EntityManager#flushhat Nebenwirkungen . Es wird bequem für Entitätstypen mit generierten ID-Werten (Sequenzwerten) verwendet: Eine solche ID ist nur bei Synchronisation mit der zugrunde liegenden Persistenzschicht verfügbar. Wenn diese ID vor dem Ende der aktuellen Transaktion erforderlich ist (z. B. zu Protokollierungszwecken), muss die Sitzung geleert werden.


0

Mit dieser Methode rufen Sie den Spülvorgang hervor. Dieser Prozess synchronisiert den Status Ihrer Datenbank mit dem Status Ihrer Sitzung, indem Statusänderungen erkannt und die entsprechenden SQL-Anweisungen ausgeführt werden.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.