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

Java 基于另一个线程结果的数据库回滚,java,spring,multithreading,jpa,concurrency,Java,Spring,Multithreading,Jpa,Concurrency,我对我的业务逻辑进行了顺序处理,包括: 将消息发送到远程服务器 将该消息保存到数据库中 Sequential.java 我意识到,如果我同时完成这两项任务,我可以提高绩效。一个线程发送消息,另一个线程将其保存到数据库 Parallel.java 并行方法的问题是,即使发生异常,消息也会保存到数据库中。如果发生异常,但仍并行运行这两个任务,是否有任何方法阻止保存 可能是某种基于触发器的回滚。一旦保存并提交了数据,就无法回滚事务。现在,您可以从另一个线程发送消息,而不是将消息保存到DB的线程。因此,

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

将消息发送到远程服务器 将该消息保存到数据库中 Sequential.java

我意识到,如果我同时完成这两项任务,我可以提高绩效。一个线程发送消息,另一个线程将其保存到数据库

Parallel.java

并行方法的问题是,即使发生异常,消息也会保存到数据库中。如果发生异常,但仍并行运行这两个任务,是否有任何方法阻止保存


可能是某种基于触发器的回滚。

一旦保存并提交了数据,就无法回滚事务。现在,您可以从另一个线程发送消息,而不是将消息保存到DB的线程。因此,您的消息可能在发送消息之前保存到DB,在这种情况下,如果在发送消息期间出现任何异常,则无法回滚。我建议使用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);
    }
});

Spring在多线程环境中不支持开箱即用的回滚,但您可以通过编程方式强制执行它。参考
// 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));
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);
    }
});