2016-07-07 8 views
1

ich einen einfachen Code Feder + JPA haben, die auf den ersten Blick korrekt aussieht:Frühling Transaktionen: innere Transaktion Änderungen werden als „Rollback“ durch äußere Transaktion (oder vielleicht JPA Missbrauch)

@Transactional(propagation=REQUIRED) 
public void outer(long id) { 
    MyEntity entity = myRepo.findById(id); 
    try { 
     // doing something that changes entity 
     // and may throw exception 
     doInOuter(entity); 
    } catch (Exception ex) { 
     anotherSpringService.inner(entity); 
     throw ex; // this rollbacks outer transaction for sure 
    } 
} 

@Transactional(propagation=REQUIRES_NEW) 
public void inner(MyEntity entity) { 
    // doing something that changes entity 
} 

Lassen Sie uns den Fall betrachten, wenn Ausnahme tritt während doInOuter() auf. Ich würde in der inneren()

  1. äußerte Transaktion, dass in einem Sperranschlag erwarten
  2. innere Transaktion suspendiert, erklärt sich die Änderungen
  3. innere Transaktion geschlossen
  4. Ausnahme in dem Sperranschlag ausgelöst wird
  5. äußere Transaktion wird zurückgesetzt
  6. Die Änderungen in der Datenbank enthalten die von intern vorgenommenen Änderungen()

Leider passiert das nicht. Alle Änderungen in beiden Fällen werden vollständig rückgängig gemacht. Ich setze die Zitate, weil ich nicht denke, dass es wegen des Rollbacks selbst passiert.

Wenn ich die innere ändern, um die Einheit noch einmal abzurufen:

@Transactional(propagation=REQUIRES_NEW) 
public void inner(MyEntity entity) { 
    entity = myRepo.findById(entity.getId()); 
    // doing something which changes entity 
} 

Der Code beginnt wie erwartet zu arbeiten, und ich tun, um die Veränderungen von inneren() in der Datenbank durchgeführt sehen.

Kann mir jemand erklären, warum das funktioniert und warum der erste Ansatz nicht wie erwartet funktioniert?

Antwort

1

Die Hibernate-Sitzung ist an die Transaktion gebunden und die Entität ist an die Sitzung gebunden. Wenn Sie also die Entität an die innere Methode übergeben, bleibt sie, da sie von der äußeren Transaktion geladen wurde, an die äußere Sitzung gebunden.

Sie sollten die Entität nicht zwischen Transaktionen teilen, wie Sie festgestellt haben.

+0

Ich habe versucht, google "Entität zwischen Transaktionen teilen", aber nichts ähnliches gefunden. Haben Sie Links, damit ich mich mit Details vertraut machen kann? –

+0

Nein. Ich habe so etwas nicht. –

+0

Ok, wenn sonst niemand antwortet, werde ich deine Antwort akzeptieren. Vielen Dank! –

Verwandte Themen