首页 > 解决方案 > 基于另一个线程结果的数据库回滚

问题描述

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

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

顺序的.java

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

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

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

并行.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即使发生异常也会将其保存到数据库中。如果发生异常,是否有任何方法可以防止保存,但仍然并行运行这两个任务?

也许某种基于触发器的回滚。

标签: javaspringmultithreadingjpaconcurrency

解决方案


保存并提交数据后,您将无法回滚事务。现在你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);
    }
});

推荐阅读