Warum brauche ich Transaction in Hibernate für schreibgeschützte Vorgänge?
Setzt die folgende Transaktion eine Sperre in die DB?
Beispielcode zum Abrufen aus der DB:
Transaction tx = HibernateUtil.getCurrentSession().beginTransaction(); // why begin transaction?
//readonly operation here
tx.commit() // why tx.commit? I don't want to write anything
Kann ich session.close()
anstelle von tx.commit()
verwenden?
Möglicherweise haben Sie tatsächlich Gründe, Transaktionen als schreibgeschützt zu kennzeichnen.
autocommit=true
, Wenn nicht explizit eine andere Option festgelegt wurde.@Transactional(readonly=true)
markieren, versetzt Spring die JDBC-Transaktion in einen Nur-Lese-Modus. Sie bestimmen also, ob in diesem Rahmen tatsächlich in DB geschrieben werden kann Transaktion. Wenn Ihre Architektur umständlich ist und einige Teammitglieder die Änderungsabfrage möglicherweise dort ablegen, wo dies nicht erwartet wird, weist Sie dieses Flag auf den problematischen Ort hin.Zusammenfassend kann man beides sagen, aber man muss die Konsequenzen verstehen.
Alle Datenbankanweisungen werden im Kontext einer physischen Transaktion ausgeführt, auch wenn wir keine expliziten Transaktionsgrenzen deklarieren (BEGIN/COMMIT/ROLLBACK).
Wenn Sie Transaktionsgrenzen nicht explizit deklarieren, muss jede Anweisung in einer separaten Transaktion ausgeführt werden (autocommit
-Modus). Dies kann sogar zum Öffnen und Schließen einer Verbindung pro Anweisung führen, es sei denn, Ihre Umgebung kann die Bindung von Verbindungen pro Thread verarbeiten.
Wenn Sie einen Service als @Transactional
Deklarieren, erhalten Sie eine Verbindung für die gesamte Transaktionsdauer, und alle Anweisungen verwenden diese einzelne Isolationsverbindung. Dies ist viel besser, als überhaupt keine expliziten Transaktionen zu verwenden.
Bei großen Anwendungen treten möglicherweise viele gleichzeitige Anforderungen auf, und Reduzierung der Anforderungsrate für die Datenbankverbindungserfassung verbessert auf jeden Fall die Gesamtleistung Ihrer Anwendung.
JPA erzwingt keine Transaktionen für Leseoperationen. Nur Schreibvorgänge lösen eine für eine Transaktion erforderliche Ausnahme aus, wenn Sie vergessen, einen Transaktionskontext zu starten. Trotzdem ist es immer besser, Transaktionsgrenzen auch für schreibgeschützte Transaktionen zu deklarieren (im Frühjahr können Sie mit @Transactional
Schreibgeschützte Transaktionen markieren, was einen großen Leistungsvorteil bietet).
Transaktionen setzen in der Tat Sperren für die Datenbank - gute Datenbank-Engines behandeln gleichzeitige Sperren auf vernünftige Weise - und sind bei schreibgeschützter Verwendung nützlich, um sicherzustellen, dass keine andere Transaktion Daten hinzufügt, die Ihre Ansicht inkonsistent machen. Sie möchten immer eine Transaktion (obwohl es manchmal sinnvoll ist, die Isolationsstufe zu optimieren, ist es am besten, dies zunächst nicht zu tun). Wenn Sie während Ihrer Transaktion nie in die Datenbank schreiben, ist das Festschreiben und Zurücksetzen der Transaktion gleich (und sehr günstig).
Wenn Sie Glück haben und Ihre Abfragen für die Datenbank so sind, dass der ORM sie immer einzelnen SQL-Abfragen zuordnet, können Sie ohne explizite Transaktionen davonkommen, abhängig vom integrierten Autocommit-Verhalten der Datenbank ORMs sind jedoch relativ komplexe Systeme, so dass es nicht ungefährlich ist, sich auf ein solches Verhalten zu verlassen, wenn Sie nicht viel mehr Arbeit darauf verwenden, zu überprüfen, was die Implementierung tatsächlich tut. Das Schreiben der expliziten Transaktionsgrenzen ist weitaus einfacher (insbesondere, wenn Sie dies mit AOP oder einer ähnlichen ORM-gesteuerten Technik tun können; ab Java 7) könnten Try-with-Resources verwendet werden auch ich nehme an).
Es spielt keine Rolle, ob Sie nur lesen oder nicht - die Datenbank muss weiterhin die Ergebnismenge verfolgen, da andere Datenbankclients möglicherweise Daten schreiben möchten, die Ihre Ergebnismenge ändern würden.
Ich habe fehlerhafte Programme gesehen, die riesige Datenbanksysteme töten, weil sie nur Daten lesen, aber niemals festschreiben, wodurch das Transaktionsprotokoll wächst, weil die Datenbank die Transaktionsdaten nicht vor einem COMMIT oder ROLLBACK freigeben kann, selbst wenn der Client nichts getan hat stundenlang.