2016-04-28 9 views
3

Betrachten habe ich eine Methode in Active Record Stil ein paar Sachen und Logging-Mechanismus zu tun:begehen Änderungen in try-catch innerhalb @Transactional

@Transactional 
public void doSmt() { 
    try { 
     someOperation(); // can throw exception 
     Logger.logIntoDb(); // if everything is OK 
    } catch {Exception e} { 
     Logger.logIntoDbWithException(e.getMessage()); // log error into db 

     throw new MyCustomException(e); 
    } 
} 

public static void logIntoDbWithException(String message) { 
    final LogEntry logEntry = new LogEntry(); 
    logEntry.setDate(new Date()); 
    logEntry.setMessage(message); 
    logEntry.persist(); 
} 

Ich möchte eine Fehlermeldung im Fehlerfall bestehen bleiben, aber wenn ich Die Ausnahme 'det rethrow' in der Transaktion catch clause wird zurückgesetzt und mein LogEntry wird nicht beibehalten. Die einzige Möglichkeit, die ich sehe, ist, flush() nach persist() manuell aufzurufen.

Gibt es eine sauberere Lösung, um dies durchzuführen?

Danke.

UPD:

Da ich eine statische Methode, die ich brauche, um gelten folgende Hack akzeptierte Antwort führt persistierenden:

public static void logIntoDbWithException(String message) { 
    new Runnable() { 
     @Transactional(propagation = Propagation.REQUIRES_NEW) 
     public void run() { 
      final LogEntry logEntry = new LogEntry(); 
      logEntry.setDate(new Date()); 
      logEntry.setMessage(message); 
      logEntry.persist(); 
     } 
    }.run(); 
} 

Antwort

4

Zum einen Aufruf flush() ist nicht nur zu tun Any good: flush() schreibt nichts, und wenn Sie den Fehler in derselben Transaktion protokollieren, wird die Einfügung zurückgesetzt.

Sie müssen daher eine neue 'geschachtelte' Transaktion starten, um den Fehler zu protokollieren.

public class A { 

    @Autowired 
    private B b; 

    @Transactional 
    public void doSmt() { 
     try { 
      someOperation(); // can throw exception 
      b.logIntoDb(); // if everything is OK 
     } catch {Exception e} { 
      b.logIntoDbWithException(e.getMessage()); // log error into db 

      throw new MyCustomException(e); 
     } 
    } 
} 

public class B{ 

    //outer transaction is still active 
    public void logIntoDb(String message) { 
     final LogEntry logEntry = new LogEntry(); 
     logEntry.setDate(new Date()); 
     logEntry.setMessage(message); 
     logEntry.persist(); 
    } 

    // 'outer' transaction will be suspended until this method completes 
    // this new transaction will commit/rollback independently of the outer transaction 
    @Transactional(propagation = Propagation.REQUIRES_NEW) 
    public void logIntoDbWithException(String message) { 
     final LogEntry logEntry = new LogEntry(); 
     logEntry.setDate(new Date()); 
     logEntry.setMessage(message); 
     logEntry.persist(); 
    } 
} 
Verwandte Themen