So rufen Sie eine benutzerdefinierte Rollback-Methode in Spring Transaction Management auf?

8

Umgebung: Spring 3, Benutzerdefinierte Transaktionsverwaltung, JDBC-Transaktionen

Ich habe gerade die Spring-Dokumente zur Verwendung der Transaktionsvorlage zur Transaktionsverwaltung gelesen. Es schien übermäßig komplex , also möchte ich fragen:

Die meisten meiner Transaktionen sind JDBC-bezogen, was bedeutet, dass ich nur einen @Transactional auf meinem Dienst deklariere. Aber jetzt Ich mache einen REST-Service-Aufruf an eine andere Site, die zurückgesetzt werden muss, wenn einer der folgenden JDBC-Vorgänge fehlschlägt . In diesem Fall werde ich den Rollback-Code bereitstellen.

Wenn ich in meiner Methode Fortschritte mache, möchte ich einen Verweis auf den REST-Serviceaufruf speichern (benötigt, um diese Aktion rückgängig zu machen), und nach einer Ausnahme möchte ich nur eine Methode myCustomRollback() namens , die auf das zuvor gespeicherte Objekt zugreifen kann.

Warum stellen Sie nicht einfach eine Map in der transactionTemplate zur Verfügung, um Sachen zu speichern und eine benutzerdefinierte Rollback-Methode für die @Transactional Annotation zu definieren?

So denke ich darüber nach, ich folge nicht der Art, wie Spring darüber denkt. Kann mir jemand helfen, die Lücke zwischen dem, was ich will, und dem, was ich im Frühjahr am effizientesten erreichen kann, zu überbrücken? Ich muss das nur für einige Spezialfälle tun.

    
David Parks 16.04.2011, 04:27
quelle

5 Antworten

0

Sie können den AfterThrowing-Hinweis verwenden (wenn eine Ausnahme ausgelöst wird) & amp; Rufen Sie Ihre Methode ( myCustmRollback() ) dort auf, Sie können TransactionSynchronizationManager class verwenden, um die aktuelle Transaktion & amp; Roll es zurück ...

alternativ ... können Sie den AroundAdvice verwenden, um & amp; Commit / Rollback Ihrer Transaktion (auf diese Weise können Sie den Spring-Transaktionsmanager mithilfe der Klasse TransactionSynchronizationManager verwenden)

    
Anantha Sharma 16.04.2011, 05:38
quelle
4

Ich habe Ihre Frage ein paar Mal neu gelesen und bin mir nicht sicher, ob ich Ihre Frage vollständig verstehe. Ich gehe davon aus, dass Sie someCode ausführen und wenn das fehlschlägt, möchten Sie myCustomRollback ausführen, das einige Informationen über someCode enthält. Also werde ich versuchen, eine generische Antwort zu geben.

Wenn Sie möchten, dass der Quellcode zurückgesetzt wird. Es wird nur Rollbackback, wie JDBC-Transaktionen. Angenommen, Sie haben eine Methode, die 2 Aufrufe durchführt.

%Vor%

Also wird der obige Code immer zurückgesetzt. Dadurch wird das Fortbestehen Ihrer Entität rückgängig gemacht, nicht jedoch die Erstellung Ihrer Datei, da diese nicht von Spring-Transaktionen verwaltet wird, sofern Sie keine benutzerdefinierte Implementierung dafür bereitstellen.

Zweitens bietet Spring zwei Möglichkeiten, mit Transaktionen zu arbeiten:

  • Spring AOP: Ein Proxy wird zur Laufzeit erstellt , der Ihren Code mit Transaktionsdaten schmückt. Wenn Ihre Klasse MyClass heißen würde, erstellt Spring einen Klassennamen MyClassProxy, der Ihren Code in Transaktionscode umschließt.
  • AspectJ: Zum Kompilieren wird Ihre .class-Datei angepasst und Transaktionscode wird in Ihre Methode eingebettet.

Der aspectJ Ansatz scheint schwieriger zu konfigurieren, ist aber nicht so viel und ist viel einfacher zu benutzen. Da alles, was mit @Transactional versehen ist, wird mit Code eingebettet (gewebt). Für Spring AOP ist dies nicht der Fall. Transaktionsinnere Methodenaufrufe zB im Frühjahr werden ignoriert! So bietet aspectJ einen intuitiveren Ansatz.

Zurück zu dem, was ich denke, ist Ihre Frage (der Code ist alles in 1 Klasse):

%Vor%

Der obige Code funktioniert nur mit AspectJ! Da Ihre innere Methode aufruft, die auch privat zu sein scheint! AOP zur Laufzeit kann damit nicht umgehen.

Was passiert, ist, dass alles (was rollbackAble ist) in execute zurückgesetzt wird. Und in doStuff haben Sie Informationen über die Objekte, die in execute verwendet wurden. Sie können nun in myCustomRollback Ihre REST-Dateien manuell zurücksetzen.

Ich bin mir nicht sicher, ob ich diese Frage richtig beantwortet habe, aber ich hoffe, es hilft jemandem mit einem ähnlichen Problem.

    
Fico 26.09.2013 07:04
quelle
3

Für alle, die noch lesen:

Ich habe ein ähnliches Problem mit Frühlingsereignissen gelöst - wie von Den Roman in Option 3 vorgeschlagen. Hier ist die Grundidee (Szenario ist fiktiv):

Immer wenn ich externe Operationen durchführe, die zusammen mit der Transaktion zurückgesetzt werden müssen, veröffentliche ich ein Ereignis in meiner @Transactional -Methode mit Unterstützung von spring ( org.springframework.context.ApplicationEventPublisher ):

%Vor%

Das Ereignis selbst kann ein beliebiges Objekt sein - Ich habe ein POJO mit Details über die entfernte Entität erstellt, die gelöscht werden soll.

Dann habe ich einen speziellen Event-Listener registriert, der an eine Transaktionsphase gebunden ist - in meinem Fall an den Rollback:

%Vor%

Natürlich ist es empfehlenswert, & amp; Protokolliere die Ausnahme von der Rollback-Operation, um die ursprüngliche Ausnahme nicht von der Methode placeOrder() zu verlieren.

Standardmäßig sind diese Ereignisse synchron, aber sie können durch zusätzliche Konfiguration async gemacht werden.

Hier ist ein sehr guter Artikel über diesen Mechanismus, einschließlich detaillierter Konfiguration und Fallstricke: Transaktionssynchronisation und Spring Application Events (DZone)

Obwohl mir die Lösung nicht 100% ig gefällt, weil sie die Geschäftslogik mit Event-Publishing stopft und an spring bindet, tut sie definitiv das, was ich von ihr erwarte, und macht es möglich, den Kontext von der transaktionalen Methode an die zu übergeben Rollback-Methode - die nicht über einen traditionellen try / catch-Block außerhalb der Transaktionsmethode verfügbar ist (es sei denn, Sie haben Ihren Kontext in die Ausnahme selbst gestellt, was nicht sehr nett ist).

    
Timi 16.11.2017 09:28
quelle
1

Spring transaction management das Standardverhalten für das automatische Rollback ist für ungeprüfte Ausnahmen

also für eine benutzerdefinierte Ausnahme,

%Vor%

Die Transaktion wird zurückgesetzt, wenn eine Ausnahme vorhanden ist, die der angegebenen entspricht. Wenn eine Ausnahme nicht übereinstimmt, wird sie an den Aufrufer des Service- oder TransactionRolledBackException-Wrappers

weitergegeben

Wenn Sie den org.springframework.transaction.PlatformTransactionManager verwenden, ist die Handhabung von Ausnahmen besser als Vorlage

Überprüfen Sie die Dokumentation Ссылка

    
zudokod 16.04.2011 09:59
quelle
0

1 Lösung besteht darin, Ihren eigenen Transaktionsmanager zu implementieren, indem Sie einen einzigen erweitern

2 Lösung ist die TransactionSynchronizationManager-Klasse

zu verwenden

3 Lösung ist die Verwendung von @TransactionalEventListener, falls Sie Spring 4 haben

    
Den Roman 26.02.2016 00:00
quelle