Spring @Transactional - Isolation, Ausbreitung


447

Kann jemand anhand eines Beispiels aus der Praxis erklären, wofür Isolations- und Ausbreitungsparameter in der @TransactionalAnnotation gelten?

Grundsätzlich, wann und warum ich mich dafür entscheiden sollte, ihre Standardwerte zu ändern.

Antworten:


442

Gute Frage, wenn auch nicht trivial zu beantworten.

Vermehrung

Definiert, wie Transaktionen zueinander in Beziehung stehen. Allgemeine Optionen:

  • Required: Code wird immer in einer Transaktion ausgeführt. Erstellt eine neue Transaktion oder verwendet eine, falls verfügbar.
  • Requires_new: Code wird immer in einer neuen Transaktion ausgeführt. Hält die aktuelle Transaktion an, falls vorhanden.

Isolation

Definiert den Datenvertrag zwischen Transaktionen.

  • Read Uncommitted: Ermöglicht Dirty Reads.
  • Read Committed: Ermöglicht keine schmutzigen Lesevorgänge.
  • Repeatable Read: Wenn eine Zeile in derselben Transaktion zweimal gelesen wird, ist das Ergebnis immer dasselbe.
  • Serializable: Führt alle Transaktionen in einer Sequenz aus.

Die verschiedenen Ebenen weisen in einer Multithread-Anwendung unterschiedliche Leistungsmerkmale auf. Ich denke, wenn Sie das dirty readsKonzept verstehen , können Sie eine gute Option auswählen.


Beispiel dafür, wann ein Dirty Read auftreten kann:

  thread 1   thread 2      
      |         |
    write(x)    |
      |         |
      |        read(x)
      |         |
    rollback    |
      v         v 
           value (x) is now dirty (incorrect)

Ein vernünftiger Standardwert (falls dies behauptet werden kann) könnte also sein Read Committed, mit dem Sie nur Werte lesen können, die bereits von anderen laufenden Transaktionen festgeschrieben wurden, in Kombination mit einer Ausbreitungsstufe von Required. Dann können Sie von dort aus arbeiten, wenn Ihre Anwendung andere Anforderungen hat.


Ein praktisches Beispiel dafür, wo beim Eingeben der provideServiceRoutine immer eine neue Transaktion erstellt und beim Verlassen abgeschlossen wird:

public class FooService {
    private Repository repo1;
    private Repository repo2;

    @Transactional(propagation=Propagation.REQUIRES_NEW)
    public void provideService() {
        repo1.retrieveFoo();
        repo2.retrieveFoo();
    }
}

Hätten wir stattdessen verwendet Required, würde die Transaktion offen bleiben, wenn die Transaktion bereits beim Aufrufen der Routine geöffnet wäre. Beachten Sie auch, dass das Ergebnis von a rollbackunterschiedlich sein kann, da mehrere Ausführungen an derselben Transaktion teilnehmen können.


Wir können das Verhalten leicht mit einem Test überprüfen und feststellen, wie sich die Ergebnisse mit den Ausbreitungsniveaus unterscheiden:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:/fooService.xml")
public class FooServiceTests {

    private @Autowired TransactionManager transactionManager;
    private @Autowired FooService fooService;

    @Test
    public void testProvideService() {
        TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
        fooService.provideService();
        transactionManager.rollback(status);
        // assert repository values are unchanged ... 
}

Mit einem Ausbreitungsgrad von

  • Requires new: Würden wir erwarten , fooService.provideService()war nicht seine eigene Unter Transaktion , da sie erstellt zurückgerollt.

  • Required: Wir würden erwarten, dass alles zurückgesetzt wurde und der Backing Store unverändert blieb.


In welcher Beziehung steht dieser letzte Link zu dem, wovon Sie sprechen? Gemäß den verknüpften Dokumenten scheint die Sitzung die aktuelle Transaktion anzugeben, nicht die Sitzungsfactory.
Donal Fellows

@Donal, oh sorry das war nicht klar. Mein Punkt war, da sessionFactory.getCurrentTransaction()hinzugefügt wurde, besteht keine Notwendigkeit HibernateTemplatemehr, um Transaktionen zu verwalten. Ich habe es entfernt :)
Johan Sjöberg

Bei meiner Frage ging es eigentlich nur darum, wohin der Link zeigte. :-)
Donal Fellows

Wie bekomme ich die Änderungen, die in der aktuellen Transaktion vorgenommen wurden ? stackoverflow.com/questions/36132667/…
Prasanna Kumar HA

304

PROPAGATION_REQUIRED = 0 ; Wenn DataSourceTransactionObject T1 bereits für Methode M1 gestartet wurde. Wenn für eine andere Methode M2 ​​ein Transaktionsobjekt erforderlich ist, wird kein neues Transaktionsobjekt erstellt. Das gleiche Objekt T1 wird für M2 verwendet

PROPAGATION_MANDATORY = 2 ; Methode muss innerhalb einer Transaktion ausgeführt werden. Wenn keine vorhandene Transaktion ausgeführt wird, wird eine Ausnahme ausgelöst

PROPAGATION_REQUIRES_NEW = 3 ; Wenn DataSourceTransactionObject T1 bereits für Methode M1 gestartet wurde und ausgeführt wird (Ausführung von Methode M1). Wenn eine andere Methode M2 ​​ausgeführt wird, wird T1 für die Dauer der Methode M2 ​​angehalten, wobei das neue DataSourceTransactionObject T2 für M2.M2 in seinem eigenen Transaktionskontext ausgeführt wird

PROPAGATION_NOT_SUPPORTED = 4 ; Wenn DataSourceTransactionObject T1 bereits für Methode M1 gestartet wurde. Wenn eine andere Methode M2 ​​gleichzeitig ausgeführt wird. Dann sollte M2 nicht im Transaktionskontext ausgeführt werden. T1 wird ausgesetzt, bis M2 fertig ist.

PROPAGATION_NEVER = 5 ; Keine der Methoden wird im Transaktionskontext ausgeführt.

Isolationsstufe: Es geht darum, wie stark eine Transaktion von den Aktivitäten anderer gleichzeitiger Transaktionen beeinflusst werden kann. Sie unterstützt die Konsistenz und lässt die Daten über viele Tabellen hinweg in einem konsistenten Zustand. Dabei werden Zeilen und / oder Tabellen in einer Datenbank gesperrt.

Das Problem mit mehreren Transaktionen

Szenario 1. Wenn die T1-Transaktion Daten aus Tabelle A1 liest, die von einer anderen gleichzeitigen Transaktion T2 geschrieben wurden. Wenn auf dem Weg T2 ein Rollback durchgeführt wird, sind die von T1 erhaltenen Daten ungültig. Beispiel a = 2 sind Originaldaten. Wenn T1 a = liest 1, die von T2 geschrieben wurde. Wenn T2-Rollback ausgeführt wird, wird a = 1 in DB auf a = 2 zurückgesetzt. Jetzt hat T1 a = 1, aber in der DB-Tabelle wird es in a = 2 geändert.

Szenario2 2. Wenn die T1-Transaktion Daten aus Tabelle A1 liest. Wenn eine andere gleichzeitige Transaktion (T2) Daten in Tabelle A1 aktualisiert. Die Daten, die T1 gelesen hat, unterscheiden sich von Tabelle A1. Weil T2 die Daten in Tabelle A1 aktualisiert hat Lesen Sie a = 1 und T2 aktualisiert a = 2. Dann a! = b.

Szenario 3 Wenn die T1-Transaktion Daten aus Tabelle A1 mit einer bestimmten Anzahl von Zeilen liest. Wenn eine andere gleichzeitige Transaktion (T2) mehr Zeilen in Tabelle A1 einfügt. Die Anzahl der von T1 gelesenen Zeilen unterscheidet sich von den Zeilen in Tabelle A1

Szenario 1 wird aufgerufen Dirty Reads.

Szenario 2 heißt Nicht wiederholbare Lesevorgänge.

Szenario 3 wird aufgerufen Phantom Reads.

Die Isolationsstufe ist also die Ausdehnung, bis zu der Szenario 1, Szenario 2, Szenario 3 verhindert werden kann. Sie können eine vollständige Isolationsstufe erhalten, indem Sie die Sperrung implementieren. Dadurch wird verhindert, dass gleichzeitig dieselben Daten gelesen und geschrieben werden. Dies wirkt sich jedoch auf die Leistung aus. Die Isolationsstufe hängt von Anwendung zu Anwendung ab, wie viel Isolation erforderlich ist.

ISOLATION_READ_UNCOMMITTED : Ermöglicht das Lesen von Änderungen, die noch nicht festgeschrieben wurden. Es leidet unter Szenario 1, Szenario 2, Szenario 3

ISOLATION_READ_COMMITTED : Ermöglicht das Lesen von gleichzeitig festgeschriebenen Transaktionen. Es kann unter Szenario 2 und Szenario 3 leiden, da andere Transaktionen möglicherweise die Daten aktualisieren.

ISOLATION_REPEATABLE_READ : Mehrere Lesevorgänge desselben Feldes führen zu denselben Ergebnissen, bis es von selbst geändert wird. Es kann unter Szenario 3 leiden. Andere Transaktionen fügen möglicherweise die Daten ein

ISOLATION_SERIALIZABLE : Szenario 1, Szenario 2, Szenario 3 tritt nie auf. Es handelt sich um eine vollständige Isolierung. Es handelt sich um eine vollständige Sperrung. Die Leistung wird aufgrund der Sperrung beeinträchtigt.

Sie können mit testen

public class TransactionBehaviour {
   // set is either using xml Or annotation
    DataSourceTransactionManager manager=new DataSourceTransactionManager();
    SimpleTransactionStatus status=new SimpleTransactionStatus();
   ;


    public void beginTransaction()
    {
        DefaultTransactionDefinition Def = new DefaultTransactionDefinition();
        // overwrite default PROPAGATION_REQUIRED and ISOLATION_DEFAULT
        // set is either using xml Or annotation
        manager.setPropagationBehavior(XX);
        manager.setIsolationLevelName(XX);

        status = manager.getTransaction(Def);

    }

    public void commitTransaction()
    {


            if(status.isCompleted()){
                manager.commit(status);
        } 
    }

    public void rollbackTransaction()
    {

            if(!status.isCompleted()){
                manager.rollback(status);
        }
    }
    Main method{
        beginTransaction()
        M1();
        If error(){
            rollbackTransaction()
        }
         commitTransaction();
    }

}

Sie können das Ergebnis mit verschiedenen Werten für die Isolierung und Weitergabe debuggen und anzeigen.


Wie bekomme ich die Änderungen, die in der aktuellen Transaktion vorgenommen wurden ? stackoverflow.com/questions/36132667/…
Prasanna Kumar HA

2
Was ist die Wechselwirkung zwischen Isolationsgrad und Ausbreitung ? Wenn Methode 1 eine Transaktion mit der Isolationsstufe READ_COMMITTED startet und später Methode 2 mit der Stufe REPEATABLE_READ aufruft, muss Methode 2 sicherlich in einer eigenen neuen Transaktion ausgeführt werden, unabhängig davon, welches Ausbreitungsverhalten sie angibt (z. B. nur REQUIRED).
Cornel Masson

Dies ist wirklich spät in der Show, aber wenn PROPAGATION_REQUIRES_NEW, was passiert mit T1 (das von M1 verwendet wird), wenn M1 erneut angerufen wird? (sagen Sie M1.1)
Tim Z.

115

Genügend Erklärungen zu jedem Parameter werden durch andere Antworten gegeben; Wie auch immer Sie nach einem Beispiel aus der realen Welt gefragt haben, hier ist das, das den Zweck der unterschiedlichen Verbreitung verdeutlicht :

Angenommen, Sie sind für die Implementierung eines Anmeldedienstes verantwortlich, bei dem eine Bestätigungs-E-Mail an den Benutzer gesendet wird. Sie haben zwei Serviceobjekte, eines zum Registrieren des Benutzers und eines zum Senden von E-Mails, das im ersten aufgerufen wird. Zum Beispiel so etwas:

/* Sign Up service */
@Service
@Transactional(Propagation=REQUIRED)
class SignUpService{
 ...
 void SignUp(User user){
    ...
    emailService.sendMail(User);
 }
}

/* E-Mail Service */
@Service
@Transactional(Propagation=REQUIRES_NEW)
class EmailService{
 ...
 void sendMail(User user){
  try{
     ... // Trying to send the e-mail
  }catch( Exception)
 }
}

Möglicherweise haben Sie bemerkt, dass der zweite Dienst vom Weitergabe-Typ REQUIRES_NEW ist und es besteht außerdem die Möglichkeit, dass er eine Ausnahme (SMTP-Server heruntergefahren, ungültige E-Mail oder aus anderen Gründen). Sie möchten wahrscheinlich nicht, dass der gesamte Prozess zurückgesetzt wird Entfernen der Benutzerinformationen aus der Datenbank oder anderen Dingen; Daher rufen Sie den zweiten Dienst in einer separaten Transaktion auf.

Zurück zu unserem Beispiel: Dieses Mal sind Sie besorgt über die Datenbanksicherheit. Definieren Sie Ihre DAO-Klassen folgendermaßen:

/* User DAO */
@Transactional(Propagation=MANDATORY)
class UserDAO{
 // some CRUD methods
}

Das heißt, wenn ein DAO-Objekt und damit ein potenzieller Zugriff auf db erstellt wird, müssen wir sicherstellen, dass der Anruf von einem unserer Dienste aus getätigt wurde, was bedeutet, dass eine Live-Transaktion vorhanden sein sollte. Andernfalls tritt eine Ausnahme auf. Daher ist die Weitergabe vom Typ OBLIGATORISCH .


26
Perfektes Beispiel für REQUIRES_NEW.
Ravi Thapliyal

5
Gute Erklärung! Übrigens, was ist die Standardeinstellung für die Weitergabe? Wäre auch noch besser, wenn Sie ein solches Beispiel auch zur Isolation geben könnten. Vielen Dank.
Prakash K


59

Die Isolationsstufe definiert, wie sich die von einer Transaktion an einem Datenrepository vorgenommenen Änderungen auf andere gleichzeitige Transaktionen auswirken und wie und wann diese geänderten Daten für andere Transaktionen verfügbar werden. Wenn wir eine Transaktion mithilfe des Spring-Frameworks definieren, können wir auch konfigurieren, in welcher Isolationsstufe dieselbe Transaktion ausgeführt wird.

@Transactional(isolation=Isolation.READ_COMMITTED)
public void someTransactionalMethod(Object obj) {

}

Die Isolationsstufe READ_UNCOMMITTED gibt an, dass eine Transaktion Daten lesen kann, die von anderen Transaktionen noch nicht festgeschrieben wurden.

Die Isolationsstufe READ_COMMITTED gibt an, dass eine Transaktion keine Daten lesen kann, die noch nicht von anderen Transaktionen festgeschrieben wurden.

Die Isolationsstufe REPEATABLE_READ gibt an, dass das Ergebnis all dieser Lesevorgänge immer dasselbe sein muss, wenn eine Transaktion einen Datensatz mehrmals aus der Datenbank liest.

Die SERIALIZABLE-Isolationsstufe ist die restriktivste aller Isolationsstufen. Transaktionen werden mit Sperren auf allen Ebenen (Lese-, Bereichs- und Schreibsperren) ausgeführt, sodass sie so aussehen, als ob sie serialisiert ausgeführt wurden.

Die Weitergabe ist die Fähigkeit zu entscheiden, wie die Geschäftsmethoden sowohl in logischen als auch in physischen Transaktionen gekapselt werden sollen.

Spring REQUIRED-Verhalten bedeutet, dass dieselbe Transaktion verwendet wird, wenn im aktuellen Ausführungskontext der Bean-Methode bereits eine Transaktion geöffnet ist.

REQUIRES_NEW-Verhalten bedeutet, dass der Container immer eine neue physische Transaktion erstellt.

Das NESTED-Verhalten bewirkt, dass verschachtelte Spring-Transaktionen dieselbe physische Transaktion verwenden, jedoch Sicherungspunkte zwischen verschachtelten Aufrufen festlegen, sodass innere Transaktionen auch unabhängig von äußeren Transaktionen zurückgesetzt werden können.

Das OBLIGATORY-Verhalten besagt, dass eine vorhandene geöffnete Transaktion bereits vorhanden sein muss. Wenn nicht, wird vom Container eine Ausnahme ausgelöst.

Das Verhalten NIE besagt, dass eine vorhandene geöffnete Transaktion noch nicht vorhanden sein darf. Wenn eine Transaktion vorhanden ist, wird vom Container eine Ausnahme ausgelöst.

Das NOT_SUPPORTED-Verhalten wird außerhalb des Bereichs einer Transaktion ausgeführt. Wenn bereits eine geöffnete Transaktion vorhanden ist, wird diese angehalten.

Das SUPPORTS-Verhalten wird im Rahmen einer Transaktion ausgeführt, wenn bereits eine geöffnete Transaktion vorhanden ist. Wenn noch keine Transaktion geöffnet ist, wird die Methode trotzdem ausgeführt, jedoch nicht transaktionsbezogen.


4
Wenn Sie hinzufügen könnten, wann welche zu verwenden sind, wäre dies viel vorteilhafter.
Kumar Manish

Geben Sie einige Beispiele, Es wäre sehr hilfreich für Anfänger
Nitinsridar

23

Eine Transaktion repräsentiert eine Arbeitseinheit mit einer Datenbank.

In-Spring- TransactionDefinitionSchnittstelle, die Spring-konforme Transaktionseigenschaften definiert. @TransactionalAnnotation beschreibt Transaktionsattribute für eine Methode oder Klasse.

@Autowired
private TestDAO testDAO;

@Transactional(propagation=TransactionDefinition.PROPAGATION_REQUIRED,isolation=TransactionDefinition.ISOLATION_READ_UNCOMMITTED)
public void someTransactionalMethod(User user) {

  // Interact with testDAO

}

Vermehrung (Reproduktion): Wird für die Intertransaktionsbeziehung verwendet. (analog zur Java Inter Thread Kommunikation)

+-------+---------------------------+------------------------------------------------------------------------------------------------------+
| value |        Propagation        |                                             Description                                              |
+-------+---------------------------+------------------------------------------------------------------------------------------------------+
|    -1 | TIMEOUT_DEFAULT           | Use the default timeout of the underlying transaction system, or none if timeouts are not supported. |
|     0 | PROPAGATION_REQUIRED      | Support a current transaction; create a new one if none exists.                                      |
|     1 | PROPAGATION_SUPPORTS      | Support a current transaction; execute non-transactionally if none exists.                           |
|     2 | PROPAGATION_MANDATORY     | Support a current transaction; throw an exception if no current transaction exists.                  |
|     3 | PROPAGATION_REQUIRES_NEW  | Create a new transaction, suspending the current transaction if one exists.                          |
|     4 | PROPAGATION_NOT_SUPPORTED | Do not support a current transaction; rather always execute non-transactionally.                     |
|     5 | PROPAGATION_NEVER         | Do not support a current transaction; throw an exception if a current transaction exists.            |
|     6 | PROPAGATION_NESTED        | Execute within a nested transaction if a current transaction exists.                                 |
+-------+---------------------------+------------------------------------------------------------------------------------------------------+

Isolation: Die Isolation ist eine der ACID-Eigenschaften (Atomicity, Consistency, Isolation, Durability) von Datenbanktransaktionen. Die Isolation bestimmt, wie die Transaktionsintegrität für andere Benutzer und Systeme sichtbar ist. Es wird zum Sperren von Ressourcen verwendet, dh zum Steuern der Parallelität. Stellen Sie sicher, dass zu einem bestimmten Zeitpunkt nur eine Transaktion auf die Ressource zugreifen kann.

Sperrwahrnehmung: Die Isolationsstufe bestimmt die Dauer, in der Sperren gehalten werden.

+---------------------------+-------------------+-------------+-------------+------------------------+
| Isolation Level Mode      |  Read             |   Insert    |   Update    |       Lock Scope       |
+---------------------------+-------------------+-------------+-------------+------------------------+
| READ_UNCOMMITTED          |  uncommitted data | Allowed     | Allowed     | No Lock                |
| READ_COMMITTED (Default)  |   committed data  | Allowed     | Allowed     | Lock on Committed data |
| REPEATABLE_READ           |   committed data  | Allowed     | Not Allowed | Lock on block of table |
| SERIALIZABLE              |   committed data  | Not Allowed | Not Allowed | Lock on full table     |
+---------------------------+-------------------+-------------+-------------+------------------------+

Lesewahrnehmung: Die folgenden 3 Arten von Hauptproblemen treten auf:

  • Dirty Reads : Liest nicht festgeschriebene Daten von einem anderen TX (Transaktion).
  • Nicht wiederholbare Lesevorgänge : Lesevorgänge, die UPDATESvon einem anderen Sender festgeschrieben wurden .
  • Phantom liest : liest festgeschrieben INSERTSund / oder DELETESvon einem anderen tx

Isolationsstufen mit verschiedenen Arten von Lesevorgängen:

+---------------------------+----------------+----------------------+----------------+
| Isolation Level Mode      |  Dirty reads   | Non-repeatable reads | Phantoms reads |
+---------------------------+----------------+----------------------+----------------+
| READ_UNCOMMITTED          | allows         | allows               | allows         |
| READ_COMMITTED (Default)  | prevents       | allows               | allows         |
| REPEATABLE_READ           | prevents       | prevents             | allows         |
| SERIALIZABLE              | prevents       | prevents             | prevents       |
+---------------------------+----------------+----------------------+----------------+

zum Beispiel


20

Sie möchten fast nie verwenden, Read Uncommitedda es nicht wirklich ACIDkonform ist. Read Commmitedist ein guter Standardstartplatz. Repeatable Readwird wahrscheinlich nur in Berichts-, Rollup- oder Aggregationsszenarien benötigt. Beachten Sie, dass viele DBs, einschließlich Postgres, Repeatable Read nicht unterstützen. Sie müssen Serializablestattdessen verwenden. Serializableist nützlich für Dinge, von denen Sie wissen, dass sie völlig unabhängig von irgendetwas anderem geschehen müssen; Denken Sie daran wie synchronizedin Java. Serialisierbar geht Hand in Hand mit REQUIRES_NEWPropagation.

Ich verwende REQUIRESfür alle Funktionen, die UPDATE- oder DELETE-Abfragen ausführen, sowie Funktionen auf "Service" -Ebene. Für DAO-Level-Funktionen, auf denen nur SELECTs ausgeführt werden, verwende ich, SUPPORTSdie an einem TX teilnehmen, wenn eines bereits gestartet wurde (dh von einer Servicefunktion aufgerufen wird).


13

Transaktionsisolation und Transaktionsausbreitung sind zwar verwandt, aber eindeutig zwei sehr unterschiedliche Konzepte. In beiden Fällen werden die Standardeinstellungen an der Client-Grenzkomponente entweder mithilfe der deklarativen Transaktionsverwaltung oder der programmatischen Transaktionsverwaltung angepasst . Details zu den einzelnen Isolationsstufen und Ausbreitungsattributen finden Sie unter den folgenden Referenzlinks.

Transaktionsisolation

Wie und wann wirken sich Änderungen, die von Abfragen in einer Transaktion vorgenommen werden, auf zwei oder mehr laufende Transaktionen / Verbindungen zu einer Datenbank aus, die für die Abfragen in einer anderen Transaktion sichtbar sind? Es bezog sich auch darauf, welche Art der Sperre von Datenbankdatensätzen verwendet wird, um Änderungen in dieser Transaktion von anderen Transaktionen zu isolieren und umgekehrt. Dies wird normalerweise von der Datenbank / Ressource implementiert, die an der Transaktion teilnimmt.

.

Transaktionsausbreitung

In einer Unternehmensanwendung für eine bestimmte Anforderung / Verarbeitung sind viele Komponenten beteiligt, um die Aufgabe zu erledigen. Einige dieser Komponenten markieren die Grenzen (Start / Ende) einer Transaktion, die in der jeweiligen Komponente und ihren Unterkomponenten verwendet wird. Für diese Transaktionsgrenze von Komponenten gibt Transaction Propogation an, ob die jeweilige Komponente an der Transaktion teilnehmen wird oder nicht und was passiert, wenn für die aufrufende Komponente bereits eine Transaktion erstellt / gestartet wurde oder nicht. Dies entspricht den Java EE-Transaktionsattributen. Dies wird normalerweise vom Client-Transaktions- / Verbindungsmanager implementiert.

Referenz:


1
Großartig, alle Infos an einem Ort, Links sind sehr hilfreich, danke @Gladwin Burboz
nitinsridar

7

Ich habe laufen outerMethod, method_1undmethod_2 mit unterschiedlichem Ausbreitungsmodus.

Unten ist die Ausgabe für verschiedene Ausbreitungsmodi.

  • Äußere Methode

    @Transactional
    @Override
    public void outerMethod() {
        customerProfileDAO.method_1();
        iWorkflowDetailDao.method_2();
    }
  • Methode 1

    @Transactional(propagation=Propagation.MANDATORY)
    public void method_1() {
        Session session = null;
        try {
            session = getSession();
            Temp entity = new Temp(0l, "XXX");
            session.save(entity);
            System.out.println("Method - 1 Id "+entity.getId());
        } finally {
            if (session != null && session.isOpen()) {
            }
        }
    }
  • Methode_2

    @Transactional()
    @Override
    public void method_2() {
        Session session = null;
        try {
            session = getSession();
            Temp entity = new Temp(0l, "CCC");
            session.save(entity);
            int i = 1/0;
            System.out.println("Method - 2 Id "+entity.getId());
        } finally {
            if (session != null && session.isOpen()) {
            }
        }
    }
      • OuterMethod - Ohne Transaktion
      • method_1 - Propagation.MANDATORY) -
      • method_2 - Nur Transaktionsanmerkung
      • Ausgabe: method_1 löst eine Ausnahme aus, dass keine Transaktion vorhanden ist
      • OuterMethod - Ohne Transaktion
      • method_1 - Nur Transaktionsanmerkung
      • method_2 - Propagation.MANDATORY)
      • Ausgabe: method_2 löst eine Ausnahme aus, dass keine Transaktion vorhanden ist
      • Ausgabe: Methode_1 behält den Datensatz in der Datenbank bei.
      • OuterMethod - Mit Transaktion
      • method_1 - Nur Transaktionsanmerkung
      • method_2 - Propagation.MANDATORY)
      • Ausgabe: Methode_2 behält den Datensatz in der Datenbank bei.
      • Ausgabe: Methode_1 behält den Datensatz in der Datenbank bei. - Hier Main Outer vorhandene Transaktion, die sowohl für Methode 1 als auch für Methode 2 verwendet wird
      • OuterMethod - Mit Transaktion
      • method_1 - Propagation.MANDATORY) -
      • method_2 - Nur Transaktionsanmerkung und löst eine Ausnahme aus
      • Ausgabe: Wenn kein Datensatz in der Datenbank verbleibt, wird ein Rollback durchgeführt.
      • OuterMethod - Mit Transaktion
      • method_1 - Propagation.REQUIRES_NEW)
      • method_2 - Propagation.REQUIRES_NEW) und löst eine 1/0 Ausnahme aus
      • Ausgabe: method_2 löst eine Ausnahme aus, sodass der Datensatz method_2 nicht beibehalten wird.
      • Ausgabe: Methode_1 behält den Datensatz in der Datenbank bei.
      • Ausgabe: Es gibt kein Rollback für Methode_1

3

Wir können dazu hinzufügen:

@Transactional(readOnly = true)
public class Banking_CustomerService implements CustomerService {

    public Customer getDetail(String customername) {
        // do something
    }

    // these settings have precedence for this method
    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
    public void updateCustomer(Customer customer) {
        // do something
    }
}

1

Sie können wie folgt verwenden:

@Transactional(propagation = Propagation.REQUIRES_NEW)
public EventMessage<ModificaOperativitaRapporto> activate(EventMessage<ModificaOperativitaRapporto> eventMessage) {
//here some transaction related code
}

Sie können dieses Ding auch verwenden:

public interface TransactionStatus extends SavepointManager {
    boolean isNewTransaction();
    boolean hasSavepoint();
    void setRollbackOnly();
    boolean isRollbackOnly();
    void flush();
    boolean isCompleted();
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.