wake-up-neo.com

Richtige Verwendung von flush () in JPA / Hibernate

Ich habe Informationen über die flush () -Methode gesammelt, bin mir jedoch nicht ganz sicher, wann und wie ich sie richtig verwenden soll. Nach meinem Verständnis wird der Inhalt des Persistenzkontexts mit der Datenbank synchronisiert, d.h. e. Herausgabe ausstehender Kontoauszüge oder Aktualisierung von Unternehmensdaten.

Jetzt habe ich folgendes Szenario mit zwei Entitäten A und B (in einer Eins-zu-Eins-Beziehung, aber nicht von JPA erzwungen oder modelliert). A hat eine zusammengesetzte PK, die manuell festgelegt wird, und ein automatisch generiertes IDENTITY-Feld recordId. Dieses recordId sollte als Fremdschlüssel für B in die Entität A geschrieben werden. Ich speichere A und B in einer einzigen Transaktion. Das Problem ist, dass der automatisch generierte Wert A.recordId In der Transaktion nicht verfügbar ist, es sei denn, ich rufe em.flush() explizit auf, nachdem ich em.persist() auf A. (Wenn ich eine automatisch generierte IDENTITY-PK habe, wird der Wert direkt in der Entität aktualisiert, aber das ist hier nicht der Fall.)

Kann em.flush() bei Verwendung innerhalb einer Transaktion Schaden anrichten?

106
MicSim

Möglicherweise sind die genauen Details von em.flush() von der Implementierung abhängig. Im Allgemeinen können JPA-Anbieter wie Hibernate die SQL-Anweisungen, die sie an die Datenbank senden sollen, im Cache speichern, bis Sie die Transaktion tatsächlich festschreiben. Wenn Sie beispielsweise em.persist() aufrufen, merkt sich Hibernate, dass eine Datenbank INSERT erstellt werden muss, führt die Anweisung jedoch erst dann aus, wenn Sie die Transaktion festschreiben. Afaik, dies geschieht hauptsächlich aus Performancegründen.

In einigen Fällen möchten Sie trotzdem, dass die SQL-Anweisungen sofort ausgeführt werden. Im Allgemeinen, wenn Sie das Ergebnis einiger Nebenwirkungen benötigen, z. B. eines automatisch generierten Schlüssels oder eines Datenbank-Triggers.

Mit em.flush() wird der interne SQL-Anweisungscache geleert und sofort in der Datenbank ausgeführt.

Fazit: Es wird kein Schaden angerichtet, nur Sie könnten (geringfügige) Leistungseinbußen erleiden, da Sie die Entscheidungen des JPA-Anbieters hinsichtlich des besten Zeitpunkts für das Senden von SQL-Anweisungen an die Datenbank außer Kraft setzen.

136
Flavio

Tatsächlich kann em.flush() mehr als nur die zwischengespeicherten SQL-Befehle senden. Es wird versucht, den Persistenzkontext mit der zugrunde liegenden Datenbank zu synchronisieren. Wenn Ihr Cache zu synchronisierende Sammlungen enthält, kann dies zu einem hohen Zeitaufwand für Ihre Prozesse führen.

Vorsicht beim Gebrauch.

2

Kann em.flush () Schaden anrichten, wenn es innerhalb einer Transaktion verwendet wird?

Ja, möglicherweise werden Sperren in der Datenbank länger als erforderlich gespeichert.

Im Allgemeinen delegieren Sie bei Verwendung von JPA die Transaktionsverwaltung an den Container (a.k.a CMT - Verwendung von @Transactional Annotation für Geschäftsmethoden). Dies bedeutet, dass eine Transaktion beim Eingeben der Methode automatisch gestartet und am Ende festgeschrieben/rückgängig gemacht wird. Wenn Sie die Datenbanksynchronisation vom EntityManager ausführen lassen, wird die Ausführung von SQL-Anweisungen erst unmittelbar vor dem Festschreiben ausgelöst, was zu kurzlebigen Sperren in der Datenbank führt. Andernfalls behalten Ihre manuell gelöschten Schreibvorgänge möglicherweise Sperren zwischen dem manuellen Leeren und dem automatischen Festschreiben bei, die je nach verbleibender Ausführungszeit der Methode lang sein können.

Beachten Sie, dass eine Operation automatisch eine Leerung auslöst: Ausführen einer systemeigenen Abfrage für dieselbe Sitzung (der EM-Status muss geleert werden, damit die SQL-Abfrage darauf zugreifen kann), Einfügen von Entitäten mit der systemeigenen generierten ID (von der Datenbank generiert) ausgelöst, so dass die EM in der Lage ist, die generierte ID abzurufen und Beziehungen ordnungsgemäß zu verwalten)

1
Gab