Ist es empfehlenswert, org.hibernate.Session.flush()
separat anzurufen ?
Wie in den org.hibernate.Session
Dokumenten gesagt ,
Muss am Ende einer Arbeitseinheit aufgerufen werden, bevor die Transaktion festgeschrieben und die Sitzung geschlossen wird (je nach Flush-Modus ruft Transaction.commit () diese Methode auf).
Könnten Sie den Zweck eines flush()
expliziten Anrufs erläutern, wenn org.hibernate.Transaction.commit()
dies bereits geschehen wird?
sessionFactory
mit der@Transactional
Annotation injizieren , wenn Sie es sich ansehen. Ab diesem Zeitpunkt muss Ihr Code nicht mehr überall transaktional sein (dies ist jedoch in einigen Situationen erforderlich).Antworten:
Im Handbuch für den Ruhezustand sehen Sie dieses Beispiel
Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); for (int i = 0; i < 100000; i++) { Customer customer = new Customer(...); session.save(customer); if (i % 20 == 0) { // 20, same as the JDBC batch size // flush a batch of inserts and release memory: session.flush(); session.clear(); } } tx.commit(); session.close();
Ohne den Aufruf der Flush-Methode würde Ihr Cache der ersten Ebene eine OutOfMemoryException auslösen
Sie können sich auch diesen Beitrag über das Spülen ansehen
quelle
flush()
synchronisiert Ihre Datenbank mit dem aktuellen Status von Objekten im Speicher, schreibt die Transaktion jedoch nicht fest. Wenn Sie also nach demflush()
Aufruf eine Ausnahme erhalten , wird die Transaktion zurückgesetzt. Sie können Ihre Datenbank mit kleinen Datenblöcken synchronisieren,flush()
anstatt große Daten auf einmal zu übertragen,commit()
und das Risiko eingehen, eine zu erhaltenOutOfMemoryException
.commit()
macht die in der Datenbank gespeicherten Daten dauerhaft. Es gibt keine Möglichkeit, Ihre Transaktion zurückzusetzen, sobald diescommit()
erfolgreich ist.quelle
Ein häufiger Fall für explizites Leeren ist, wenn Sie eine neue persistente Entität erstellen und möchten, dass ihr ein künstlicher Primärschlüssel generiert und zugewiesen wird, damit Sie ihn später in derselben Transaktion verwenden können. In diesem Fall würde das Aufrufen von Flush dazu führen, dass Ihrer Entität eine ID zugewiesen wird.
Ein anderer Fall ist, wenn der Cache der ersten Ebene viele Dinge enthält und Sie ihn regelmäßig löschen möchten (um den vom Cache verwendeten Speicherplatz zu reduzieren), Sie aber trotzdem das Ganze zusammenschreiben möchten . Dies ist der Fall, den Alekseis Antwort abdeckt.
quelle
.refresh(...)
flush();
Beim Flushing wird der zugrunde liegende persistente Speicher mit dem im Speicher gespeicherten persistenten Status synchronisiert. Es wird in der laufenden Transaktion aktualisiert oder in Ihre Tabellen eingefügt, diese Änderungen werden jedoch möglicherweise nicht festgeschrieben.Commit();
Beim Festschreiben wird die Datenbank festgeschrieben. Wenn Sie ein dauerhaftes Objekt haben und einen Wert darauf ändern, wird es verschmutzt und der Ruhezustand muss diese Änderungen in Ihre Persistenzschicht übertragen. Sie sollten sich also verpflichten, aber es beendet auch die Arbeitseinheit (transaction.commit()
).quelle
Es wird normalerweise nicht empfohlen, Flush explizit aufzurufen, es sei denn, dies ist erforderlich. Im Ruhezustand ruft Flush normalerweise am Ende der Transaktion automatisch auf, und wir sollten es funktionieren lassen. In einigen Fällen müssen Sie möglicherweise explizit Flush aufrufen, wobei eine zweite Aufgabe vom Ergebnis der ersten Persistenzaufgabe abhängt, die sich beide in derselben Transaktion befinden.
Beispielsweise müssen Sie möglicherweise eine neue Entität beibehalten und dann die ID dieser Entität verwenden, um eine andere Aufgabe innerhalb derselben Transaktion auszuführen. In diesem Fall muss die Entität zuerst explizit geleert werden.
@Transactional void someServiceMethod(Entity entity){ em.persist(entity); em.flush() //need to explicitly flush in order to use id in next statement doSomeThingElse(entity.getId()); }
Beachten Sie außerdem, dass das explizite Leeren kein Datenbank-Commit verursacht. Ein Datenbank-Commit wird nur am Ende einer Transaktion durchgeführt. Wenn also nach dem Aufruf von Flush ein Laufzeitfehler auftritt, werden die Änderungen weiterhin rückgängig gemacht.
quelle
Standardmäßig ist der Flush-Modus AUTO. Dies bedeutet: "Die Sitzung wird manchmal vor der Ausführung der Abfrage geleert, um sicherzustellen, dass Abfragen niemals den veralteten Status zurückgeben." Die Sitzung wird jedoch meistens geleert, wenn Sie Ihre Änderungen festschreiben. Der manuelle Aufruf der Flush-Methode ist nützlich, wenn Sie FlushMode = MANUAL verwenden oder eine Optimierung durchführen möchten. Aber ich habe das noch nie gemacht, deshalb kann ich Ihnen keine praktischen Ratschläge geben.
quelle
session.flush () ist eine Synchronisierungsmethode, mit der Daten nacheinander in die Datenbank eingefügt werden. Wenn wir diese Methode verwenden, werden Daten nicht in der Datenbank gespeichert, sondern im Cache. Wenn in der Mitte eine Ausnahme auftritt, können wir damit umgehen. Commit () speichert jedoch Daten in der Datenbank. Wenn wir dann mehr Daten speichern, besteht möglicherweise die Möglichkeit, dass die Speicherausnahme ausfällt, wie im JDBC-Programm im Thema Speicherpunkt
quelle