java - data - cometer cambios en try-catch dentro de @Transactional
spring jpa configuration (1)
En primer lugar, llamar a flush () no te va a servir de nada: flush () no confirma nada y, como estás registrando el error en la misma transacción, la inserción se revertirá.
Por lo tanto, debe iniciar una nueva transacción ''anidada'' para registrar el error.
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();
}
}
Considere que tengo un método para hacer algunas cosas y el mecanismo de registro en el estilo del patrón ActiveRecord:
@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();
}
Deseo persistir un mensaje de error en caso de error, pero si reimpré la excepción en catch, la transacción se retrotraerá y mi LogEntry no se conservará. La única forma que veo es llamar manualmente flush()
después de persist()
.
¿Hay una solución más limpia para realizar esto?
Gracias.
UPD:
Como tengo un método estático que persiste, necesito aplicar el siguiente hack a la respuesta aceptada:
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();
}