基于另一个线程结果的数据库回滚

时间:2018-07-28 10:42:55

标签: java spring multithreading jpa concurrency

我对我的业务逻辑进行了顺序处理,其中包括:

  1. 将消息发送到远程服务器
  2. 将该消息保存到数据库

Sequential.java

try {
   sender.send(message); // throws SendingException
} catch (SendingException e) {throw SomeException("Couldn't send.", e);}

dbService.save(message); // save only if successfully sent

我意识到,如果同时执行这两项任务,则可以提高性能。一个线程发送消息,另一个线程将消息保存到数据库。

Parallel.java

// send: 1st thread
executor.execute(() -> {
    try {
        sender.send(message);
    } catch(SendingException e) {throw SomeException("Couldn't send.", e);}

});

// save: 2nd thread
executor.execute(() -> dbService.save(message));

parallel方法的问题在于,即使发生了异常,message也将保存到数据库中。如果发生异常,有什么方法可以防止保存,但是仍然并行运行这两个任务?

也许是基于触发器的回滚。

1 个答案:

答案 0 :(得分:1)

一旦保存并提交了数据,您将无法回滚事务。现在,您从send the message到数据库的线程之外的其他线程saving the message。因此,您的消息可能会保存到DB before the sending message,在这种情况下,如果在发送消息期间有任何exception,则无法回滚。我建议像下面这样使用CompletableFuture

CompletableFuture.supplyAsync(() -> {
    // send message from here
    System.out.println("Msg send");
    return msg;
}).exceptionally(ex -> {
    // handle the exception
    System.out.println("Exception occour");
    return "";
}).thenAccept((msgTosave) -> {
    if (!msgTosave.isEmpty()) {
        // save your msg to db here
        System.out.println("Msg To save : " + msgTosave);
    }
});