Die Hauptforschung in diesem Artikel ist die Spring Transaction Propagation und ihre Implementierungsprinzipien, die wie folgt eingeführt werden.
Der Spring ist derzeit ein De -facto -Standard für die Java -Entwicklung, dank seiner Bequemlichkeit, vollständigen Funktionen und einfach zu bedienen. Während des Entwicklungsprozesses ist der Betrieb von DB eine sehr häufige Operation, und wenn es um DB geht, beinhaltet es Transaktionen. Während des normalen Entwicklungsprozesses von Transaktionen, auch wenn Sie es nicht bemerken, gibt es keine Nebenwirkungen auf die normale Ausführung des Programms. Wenn jedoch eine Ausnahme auftritt und die Transaktion nicht ordnungsgemäß abgewickelt wird, können unerwartete Ergebnisse auftreten. Der Frühling hat verschiedene Operationen in Bezug auf Transaktionen, insbesondere die Entstehung von deklarativen Transaktionen, zusammengefasst, wodurch die Entwicklung komfortabler wird. Spring erweitert Transaktionen und unterstützt die Definition mehrerer Ausbreitungsattribute, was auch im Mittelpunkt dieses Artikels steht.
Nicht streng genommen ist eine Transaktion die Abkürzung mehrerer Operationen. Diese Operationen werden entweder wirksam oder keiner von ihnen wirksam (gleichwertig, nicht ausgeführt zu werden). Ein allgemeiner Betriebsprozess wird wie folgt vereinfacht:
try {Connection conn = getConnection (); // einige Datenbankoperationen durchführen} catch (Ausnahme e) {conn.rollback ();} endlich {conn.close ();}Einige Probleme sind aus dem obigen Code zu sehen:
Spring liefert deklarative Transaktionen, sodass wir nicht auf die spezifische Implementierung der zugrunde liegenden Schicht achten und viele verschiedene Implementierungsdetails der zugrunde liegenden Schicht blockiert. Um die Feinsteuerung von Transaktionen durch mehrere komplexe Unternehmen zu unterstützen, liefert Spring die Ausbreitungsmerkmale von Transaktionen und in Kombination mit deklarativen Transaktionen zu einem wichtigen Transaktionswerkzeug.
In der Transaktionsdefinitionsklasse bietet Spring 6 Propagationseigenschaften, die mit einfachen Beispielen erläutert werden.
Warme Erinnerung: Das folgende erwähnte Verbinden der aktuellen Transaktion bezieht sich auf die Verwendung derselben Verbindung am Boden, das Transaktionszustandsobjekt kann jedoch nachgebildet werden und wirkt sich nicht aus. In dem Artikel wurde erwähnt, dass derzeit nur eine Transaktion besteht, was bedeutet, dass die zugrunde liegende Verbindung geteilt wird und sich nicht darum kümmert, wie viele Transaktionszustandsobjekte (TransactionStatus) erstellt werden.
Beschreibung: Wenn bereits eine Transaktion vorhanden ist, schließen Sie die Transaktion bei. Wenn es keine Transaktion gibt, erstellen Sie eine Transaktion. Dies ist der Standard -Attributwert für Ausbreitung.
Sehen wir uns ein kleines Beispiel an, der Code ist wie folgt:
@Transactionalpublic void Service () {servicea (); serviceB ();}@transactionalServicea ();@transactionalServiceb ();servicea und serviceB deklarieren beide Transaktionen. Standardmäßig propagation = propagation_required. Während des gesamten Service -Anrufprozesses gibt es nur eine gemeinsame Transaktion. Wenn eine Ausnahme eintritt, werden alle Vorgänge zurückgerollt.
Beschreibung: Wenn bereits eine Transaktion vorhanden ist, verbinden Sie die Transaktion, andernfalls wird eine sogenannte leere Transaktion erstellt (sie kann als keine Transaktionsausführung angesehen werden).
Sehen wir uns ein kleines Beispiel an, der Code ist wie folgt:
public void Service () {servicea (); neue RunTimeException ();}@transactional (Propagation = Propagation.Supports) servicea () werfen;Derzeit gibt es keine Transaktion, wenn Servicea ausgeführt wird. Die Ausnahme, die im Service ausgelöst wird, wird nicht dazu führen, dass Servicea Rollback.
Schauen wir uns ein weiteres kleines Beispiel an, der Code lautet wie folgt:
public void Service () {servicea ();}@transactional (Propagation = Propagation.Supports) servicea () {do SQL 1 1/0; SQL 2} machenDa Servicea beim Ausführen keine Transaktionen hat, ist SQL1 zu diesem Zeitpunkt effektiv, wenn die zugrunde liegende Datenquelle defaultAutocommit = true ist. Wenn defaultAutocommit = false ist, ist SQL1 ungültig. Wenn der Dienst über das @transactional -Tag verfügt, teilt Servicea die Service -Transaktionen (stützt sich nicht mehr auf defaultAutocommit). Zu dieser Zeit ist Servicea alle zurückgerollt.
Beschreibung: Derzeit muss eine Transaktion vorhanden sein, andernfalls wird eine Ausnahme ausgelöst.
Sehen wir uns ein kleines Beispiel an, der Code ist wie folgt:
public void Service () {serviceB (); servicea ();} serviceB () {do sql} @transactional (Propagation = Propagation.Mandatory) servicea () {do SQL}In diesem Fall wird der Ausführungsdienst eine Ausnahme ausgeben. Wenn defaultAutocommit = true, wird ServiceB nicht zurückrollen. Wenn defaultAutocommit = false ist, ist die ServiceB -Ausführung ungültig.
HINWEIS: Wenn derzeit eine Transaktion vorliegt, verkapseln Sie zunächst den aktuellen Transaktionsinhalt in eine Entität, dann eine neue Transaktion neu, akzeptieren Sie diese Entität als Parameter und verwenden Sie sie für die Wiederherstellung der Transaktion. Eine stumpfere Anweisung besteht darin, die aktuelle Transaktion auszusetzen (keine Transaktion ist erforderlich) und eine neue Transaktion zu erstellen. In diesem Fall gibt es keine Abhängigkeit zwischen den beiden Transaktionen, und die neue Transaktion kann zurückgeführt werden, aber die externe Transaktion führt weiterhin aus.
Sehen wir uns ein kleines Beispiel an, der Code ist wie folgt:
@Transactionalpublic void Service () {serviceB (); versuche {servicea (); } catch (Ausnahme e) {}} serviceB () {do SQL} @transactional (Propagation = Propagation.Requires_New) servicea () {do SQL 1 1/0; SQL 2} machenBei der Aufrufen der Serviceschnittstelle erstellt Servicea, die verwendet wird, eine neue Transaktion. Da Servicea jedoch eine Laufzeitausnahme ausführt, wird Servicea zurückgerollt. In der Service -Methode werden Ausnahmen erfasst, sodass ServiceB normal eingereicht wird. Beachten Sie, dass der Versuch, den Catch -Code im Dienst, erforderlich ist, andernfalls wird der Dienst eine Ausnahme ausgelöst, wodurch der ServiceB zurückgerollt wird.
Hinweis: Wenn derzeit eine Transaktion vorliegt, die aktuelle Transaktion aussetzen und dann die neue Methode in einer Umgebung ohne Transaktionen und in einer Umgebung ohne Spring -Transaktionen ausgeführt wird, hängt der Commit von SQL vollständig vom Eigentumswert von DefaultAutocommit ab.
Sehen wir uns ein kleines Beispiel an, der Code ist wie folgt:
@Transactionalpublic void Service () {serviceB (); servicea ();} serviceB () {do sql} @transactional (Propagation = Propagation.not_supported) servicea () {do SQL 1 1/0; SQL 2} machenWenn die Servicemethode aufgerufen wird, wird eine Ausnahme ausgelöst, wenn der 1/0 -Code in der Servicea -Methode ausgeführt wird. Da Servicea in einer transaktionsfreien Umgebung liegt, hängt die effektive SQL1 vom Wert von DefaultAutocommit ab. Wenn defaultAutocommit = true ist, ist SQL1 effektiv, aber ServiceB wird zurückgerollt, da der Service eine Ausnahme ausgelöst hat.
Beschreibung: Wenn derzeit eine Transaktion vorhanden ist, wird eine Ausnahme ausgelöst, andernfalls wird der Code in einer transaktionslosen Umgebung ausgeführt.
Sehen wir uns ein kleines Beispiel an, der Code ist wie folgt:
public void Service () {serviceB (); servicea ();} serviceB () {do sql} @transactional (Propagation = Propagation.Never) servicea () {do SQL 1 1/0; SQL 2} machenNach dem obigen Beispiel ruft der Dienst auf, wenn defaultAutocommit = true, die ServiceB -Methode und SQL1 in Servicea wirksam werden.
Hinweis: Wenn derzeit eine Transaktion vorhanden ist, verwenden Sie die SavePoint -Technologie, um den aktuellen Transaktionszustand zu speichern, und dann teilt die zugrunde liegende Ebene eine Verbindung. Wenn ein Fehler in verschachtelten Auftritten auftritt, wird er selbst zum SavePoint -Status zurückgeführt. Solange eine Ausnahme von außen gefangen wird, kann sie weiterhin externe Transaktionen begehen, ohne durch das eingebettete Geschäft gestört zu werden. Wenn jedoch eine Ausnahme durch die externe Transaktion ausgelöst wird, wird die gesamte große Transaktion zurückgerollt.
HINWEIS: Der Feder Configuration Transaction Manager muss aktiv nestransactionallowed = true angeben, wie unten gezeigt:
<bean id = "DataTransactionManager"> <Eigenschaft name = "dataSource" ref = "datadataSource" /> <Eigenschaft name = "nestransactionlowed" value = "true" /> < /bean>
Siehe ein kleines Beispiel: Der Code lautet wie folgt:
@Transactionalpublic void Service () {servicea (); try {serviceB (); } catch (Ausnahme e) {}} servicea () {do sql} @transactional (Propagation = Propagation.Nested) serviceB () {do SQL1 1/0; SQL2} machenServiceB ist ein eingebetteter Service, und eine Laufzeitausnahme wird intern ausgelegt, sodass ServiceB zurückgerollt wird. Da der Service die Ausnahme eingereicht hat, kann Servicea sie normal einreichen.
Schauen wir uns ein anderes Beispiel an, der Code lautet wie folgt:
@Transactionalpublic void Service () {servicea (); ServiceB (); 1/0;}@transactional (Propagation = Propagation.Nested) servicea () {do sql} serviceB () {do SQL}Da der Service eine Ausnahme ausgelöst hat, wird die gesamte Servicemethode zurückgerollt. (Dies unterscheidet sich von Propagation_Requires_New. Eingebettete Dienste im verschachtelten Modus werden durch Ausnahmen von externen Transaktionen zurückgeführt.)
Die obigen Beispiele veranschaulichen mehrere Ausbreitungsattribute, die durch Spring -Transaktionen bereitgestellt werden, um eine Vielzahl unterschiedlicher Geschäftsanforderungen zu erfüllen, die vom Unternehmen bestimmt werden können. Schauen wir uns anschließend an, was die wichtigsten technischen Abhängigkeiten von Frühling diese Ausbreitungsattribute implementiert. Dieser Abschnitt listet die Propagation_Requires_new und Propagation.nested für kurze Beschreibungen auf.
Der folgende Code -Anruf:
@Transactionalpublic void Service () {serviceB (); versuche {servicea (); } catch (Ausnahme e) {}}@transactional (Propagation = Propagation.Requires_New) servicea () {do SQL 1 1/0; do SQL 2} serviceB () {do SQL}Das Ausführungsschema lautet wie folgt:
A. Erstellen Sie ein Transaktionszustandsobjekt, erhalten Sie eine neue Verbindung, setzen
B. Binden Sie die Verbindung an die ThreadLocal -Variable
C. Bis zur aktuellen Transaktion und der Einkapselung des aktuellen Transaktionszustandsobjekts, der Verbindung und anderer Informationen in ein SuspendedResources -Objekt, das zur Wiederherstellung verwendet werden kann
D. Erstellen Sie ein neues Transaktionszustandsobjekt, rekirieren Sie eine neue Verbindung, setzen Sie das AutoCommit, das Fetchsize, die Zeitüberschreitung und andere Eigenschaften der neuen Verbindung zurück. Speichern Sie gleichzeitig das Objekt SuspendedResources für die Wiederherstellung der Transaktion und binden Sie die neue Verbindung an die ThreadLocal -Variable (Überschreibvorgang)
e. Fangen Sie eine Ausnahme an, rollen Sie die Verbindung in ThreadLocal zurück, stellen Sie die Verbindungsparameter wieder her, schließen Sie die Verbindung und stellen Sie SuspendedResources wieder her
F. Senden Sie die Verbindung in der ThreadLocal -Variablen (die dazu führt, dass ServiceB eingereicht wird), stellen Sie die Verbindungsparameter wieder her, schließen Sie die Verbindung und geben Sie die Verbindung an die Datenquelle zurück
Das Ergebnis der Programmausführung ist also, dass Servicea zurückgerollt und ServiceB erfolgreich eingereicht wird.
Der folgende Code -Anruf:
@Transactionalpublic void Service () {servicea (); try {serviceB (); } catch (Ausnahme e) {}} servicea () {do sql} @transactional (Propagation = Propagation.Nested) serviceB () {do SQL1 1/0; SQL2} machenDas Ausführungsschema lautet wie folgt:
A. Erstellen Sie ein Transaktionszustandsobjekt, erhalten Sie eine neue Verbindung, setzen
B. Binden Sie die Verbindung an die ThreadLocal -Variable
C. Markieren Sie die Verwendung des aktuellen Transaktionszustandsobjekts, erhalten Sie das ThreadLocal -Verbindungsobjekt, speichern Sie den Speicherpunkt der aktuellen Verbindung und wird für die Wiederherstellung der Ausnahme verwendet. Der Savepoint ist zu diesem Zeitpunkt der Status, nachdem die Servicea ausgeführt wurde
D. Fangen Sie eine Ausnahme an und verwenden Sie SavePoint in C für Transaktionsrollback, dh den Staat nach der Ausführung von Servicea zurück in den Staat. Alle Ausführungen von ServiceB -Methoden werden nicht wirksam
e. Rufen Sie das Verbindungsobjekt in ThreadLocal ab, senden Sie Transaktionen, stellen Sie die Verbindungseigenschaften wieder her und schließen
Basierend auf der zugrunde liegenden Datenquelle verwendet Spring ThreadLocal, SavePoint und andere technische Punkte, um eine Vielzahl von Transaktionsausbreitungsattributen zu realisieren, was die Implementierung verschiedener komplexer Dienste erleichtert. Nur durch das Verständnis des Prinzips der Ausbreitungsattribute können wir die Federtransaktionen besser kontrollieren. Feder -Rollback -Transaktionen beruhen auf der Erfassung von Ausnahmen. Standardmäßig werden Transaktionen nur zurückgerollt, wenn die RunTimeException und der Fehler geworfen werden. Natürlich kann es konfiguriert werden. Für weitere Informationen können Sie die @Transactional -Annotation überprüfen.
Die deklarativen Transaktionen des Frühlings bringen uns große Bequemlichkeit. Um diese Waffe gut zu nutzen, ist es immer noch notwendig, die zugrunde liegenden Prinzipien zu verstehen. Dieser Artikel ist nur die Spitze des Eisbergs der Federtransaktionen. Die Leser können auf dieser Grundlage eingehend untersuchen.
Das obige ist der gesamte Inhalt dieses Artikels über die Ausbreitung der Spring -Transaktion und seine Implementierungsprinzipien. Ich hoffe, es wird für alle hilfreich sein. Interessierte Freunde können weiterhin auf andere verwandte Themen auf dieser Website verweisen. Wenn es Mängel gibt, hinterlassen Sie bitte eine Nachricht, um darauf hinzuweisen. Vielen Dank an Freunde für Ihre Unterstützung für diese Seite!