2010-12-09 4 views
18

Referenzierung Spring documentation:Best Practices für die Transaktionen in Spring 3/Hibernate Rollback

Alle Runtime wird Rollback auslösen, und jede geprüfte Ausnahme nicht

javapractices.com Referenzierung

Ungeprüfter Ausnahmen:

  • repräsentieren Fehler im Programm (Bugs) - oft ungültige Argumente an eine nicht-private Methode übergeben. Um Zitat aus dem Java-Programmierung Sprache, von Gosling, Arnold und Holmes: „Ungeprüfter Laufzeit Ausnahmen Bedingungen darstellen, die im Allgemeinen sprechen, reflektieren Fehler in Ihrem Logik des Programms und nicht vernünftigerweise von zur Laufzurückgewonnen werden kann Zeit . "
  • sind Subklassen von Runtime, und sind in der Regel mit Illegal, Nullpointer implementiert, oder Illegal
  • ein Verfahren ist nicht verpflichtet, eine Politik für die ungeprüften Ausnahmen durch ihre Umsetzung (und sie fast immer tun, nicht geworfen zu etablieren so)

Checked Ausnahmen:

  • repräsentieren ungültige Bedingungen in Bereichen außerhalb des unmittelbaren con trol von das Programm (ungültige Benutzereingabe, Datenbankprobleme, Netzwerkausfälle, fehlen Dateien)
  • sind Unterklassen von Exception
  • ein Verfahren, eine Politik zu etablieren ist verpflichtet, für alle Ausnahmen durch ihre Umsetzung geworfen geprüft (entweder die geprüfte Ausnahme passiert weiter nach oben den Stapel oder handhabt es irgendwie)

Wenn während meiner Geschäftslogik ich ein Problem entdecken, und ich möchte die Änderungen rückgängig zu machen, ich habe einen neuen Run werfen Zeitausnahme? Es ist nicht wirklich eine RuntimeException (unchecked Ausnahme), da ich es in der Logik identifiziert habe. Oder verstehe ich diese Konzepte vielleicht falsch?

Meine eigentliche Frage, was das Beste Praktiken zum Walzen einer Transaktion in meiner @Transactional Service-Methoden zurück?

Antwort

10

Wenn Sie mit Ausnahmen überprüft Sie einfach auf die rollbackFor Eigentum Ihrer @Transactional Anmerkung hinzuzufügen.

@Transactional(rollbackFor = { MyInvalidUserException.class, MyApplicationException.class }) 
public void method() throws MyInvalidUserException, MyApplicationException { 
    ... 
    ... 
} 

usw.

org.life.java Antwort funktioniert auch gut. Es ist eine akademische Entscheidung, wenn Sie das programmatische Transaktionsmanagement in Ihre deklarativen Transaktionen mischen oder strikt deklarativ halten wollen.

+1

Wie kann ich etwas von meiner Methode zurückgeben, wenn ich werfe eine Ausnahme? Darüber hinaus ist das Auslösen einer Ausnahme ziemlich kostspielig. Ist es nicht möglich, die Transaktion manuell rückgängig zu machen, ohne eine Ausnahme auszulösen? –

+0

@GuillaumePolet Man könnte dem entgegenwirken, dass wenn man absichtlich Dinge im Rahmen eines nicht-außergewöhnlichen Geschäftsprozessablaufs zurückführt, die mit Rollbacks in einem RDBMS verbundenen Kosten um Größenordnungen irgendwelche realen oder wahrgenommenen Kosten einer Ausnahme auf einem modernen Server übersteigen JVM, und das ganze Design sollte überarbeitet werden. Unabhängig davon, ob Sie die Funktionsweise deklarativer Transaktionen nicht mögen ... benutzen Sie sie nicht. Das Feature ist keineswegs Ihre einzige Option. Sie können weiterhin normale alte Ruhe-Sitzungs-Transaktionen verwenden. – Affe

4

Es sollte sein wie

@Transactional 
public void method() throws YourCustomException { 
    try{ 
      //logic 
    }catch(Exception ex){ 
      TransactionAspectSupport.currentTransactionStatus() 
         .setRollbackOnly(); 
      throw(new YourCustomException(ex.getMessage())); 
    } 
} 
+5

... und * warum * sollte es so sein? – meriton

+0

@meriton Es wird für den ganzen Fall funktionieren, ich meine Ihre Absicht zu zeigen, dass dieser Service diese Ausnahme wirft wird gelöst werden sowie Ihre transaktionalen Dinge werden auch –

2

Ich denke es ist sicher zu sagen, dass es verschiedene Meinungen gibt, welche Ausnahmen überprüft werden sollten. Betrachten wir zum Beispiel diesen Auszug aus Introduction to the Spring Framework:

The Spring Datenzugriffsausnahme Hierarchie basiert auf ungeprüften (Runtime) Ausnahmen. Ich habe mit Frühling auf mehreren Projekten gearbeitet, ich bin mehr und mehr davon überzeugt, dass dies die richtige Entscheidung war.

Datenzugriffsausnahmen normalerweise nicht wiederherstellbar. Zum Beispiel, wenn wir nicht Verbindung mit der Datenbank herstellen können, ist ein bestimmtes Business-Objekt wahrscheinlich nicht möglich, um das Problem zu umgehen. Eine potenzielle Ausnahme ist optimistisch Sperrverletzungen, aber nicht alle Anwendungen verwenden optimistische Sperren. Es ist normalerweise schlecht, gezwungen zu werden, Code zu schreiben, um fatale Ausnahmen zu fangen, die nicht vernünftig gehandhabt werden können. Lassen sie zu Top-Level-Handler wie der Servlet oder EJB Container propagieren ist in der Regel geeigneter. Alle Spring Datenzugriffsausnahmen sind Unterklassen von DataAccessException, also wenn wir wählen, um alle Spring Data Access Ausnahmen zu fangen, können wir dies leicht tun.

Beachten Sie, dass, wenn wir von einem ungeprüften Datenzugriff Ausnahme wiederherstellen möchten, können wir dies dennoch tun. Wir können Code schreiben, um nur die behebbare Bedingung zu behandeln. Zum Beispiel, wenn betrachten wir, dass nur eine optimistische Verriegelungs Verletzung einbringbar ist, wir kann Code in einem Frühlings-DAO schreiben, wie folgt:

try {// do Arbeit} catch (OptimisticLockingFailureException ex) {//Ich bin daran interessiert} Wenn Spring Datenzugriff Ausnahmen wurden überprüft, müssten wir den folgenden Code schreiben. Beachten Sie, dass wir konnten wählen, dies zu schreiben trotzdem:

try {// do Arbeit} catch (OptimisticLockingFailureException ex) {// Ich habe Interesse an diesem} catch (DataAccessException ex) {// Fatal; wiederholen Sie es einfach} Ein potenzieller Einwand gegen das erste Beispiel - das der Compiler kann nicht erzwingen Handhabung die potenziell behebbare Ausnahme - gilt auch für die zweite. Da wir gezwungen sind, die Basis-Ausnahme (DataAccessException) abzufangen, erzwingt der Compiler keine Überprüfung für eine Unterklasse (OptimisticLockingFailureException). So würde der Compiler uns zwingen, Code schreiben, um ein nicht behebbares Problem zu behandeln, aber keine Hilfe in uns zwingen, mit dem behebbaren Problem zu beschäftigen.

Spring Verwendung von ungeprüften Datenzugriff Ausnahmen steht im Einklang mit der von viele - wohl - erfolgreiche Persistenz-Frameworks. (In der Tat, es wurde teilweise von JDO inspiriert.) JDBC ist eine der wenigen Datenzugriffs-APIs zu verwenden überprüft Ausnahmen. Beispielsweise verwenden TopLink und JDO, , ausschließlich die nicht aktivierten Ausnahmen . Hibernate wechselte von zu ungeprüften Ausnahmen in Version geprüft 3.

Datenzugriff Ausnahmen deutlich außerhalb der unmittelbaren Kontrolle des Programms sind, so nach javapractices, sollten sie überprüft werden. Aber die Leute an der Quelle unterscheiden sich. Und ich vertraue ihrem Urteil mehr als javapractices.

Daher sehe ich nichts falsch mit dem Auslösen einer nicht aktivierten Ausnahme, um anzuzeigen, dass die Transaktion zurückgesetzt werden soll. Natürlich können Sie auch überprüfte Ausnahmen verwenden und den Aspekt für das Rollback konfigurieren. (Siehe Antwort des Affen für weitere Details)

6

Entweder Rollback programmatisch aus:

@Transactional 
public void commit() { 
    try { 
    // some business logic... 
    } catch (ConstraintViolationException e) { 
    // trigger rollback programmatically 
    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 
    } 
} 

oder die Ausnahme für Rollbacks markieren und vom Anrufer handhaben:

@Transactional(rollBackFor = TransactionException.class) 
public void commit() throws ConstraintViolationException{ 
    try { 
    // some business logic... 
    } catch (ConstraintViolationException e) { 
    // handle the exception 
    // re-throw for rollback 
    new TransactionException(e); 
    } 
} 

public void doCommit(){ 
    try { 
    commit() 
    } catch (TransactionException e){ 
    // do nothing as already handled 
    } 
} 

ziehe ich die ersteren als es hält der Code einfacher, aber es ist discouraged nach Spring-Dok:

Programmatic Rollback ist verfügbar, wenn Sie es unbedingt brauchen, aber seine Verwendung fliegt angesichts der Erreichung einer sauberen POJO-basierten Architektur.