当前位置: 首页 > 知识库问答 >
问题:

在调用另一个事务性方法的异步方法中回滚

柳宏深
2023-03-14

我有一个非事务性和异步方法,它调用同一服务的其他事务性方法。

如果发生了什么事情,我会捕获一个异常,如果发生了什么事情,我会保存错误,但回滚不起作用。

@Service
@Transactional(readOnly = true)
public class PlayerServiceImpl implements PlayerService {

    @Inject
    PlayerRepository playerRepository;

    @Override
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
    public void save(PlayerEntity player) {
        //more code here
        playerRepository.save(player);
    }

    //other methods
}
    @Service
    public class TeamServiceImpl implements TeamService {

        @Inject
        TeamRepository teamRepository;

        @Inject
        MessageRepository messageRepository;

        @Inject
        ErrorRepository errorRepository;    

        @Inject
        PlayerService playerService;    


        @Async("asyncExecutor")
        @Override
        public void saveWithPlayersAsync(TeamEntity team, User user) {

            MessageEntity message = new MessageEntity();

            try {

    //I want rollback this if something wrong happens
                this.savePlayersA(team);
                this.savePlayersB(team);
                message.setContent("Ok !");
            } catch (TeamException e) {
                //e.printStackTrace();
                message.setContent("Fail !");           
                message.setUser(user)
//I save the error for audit
                errorRepository.save(new Error("Fail", user.getCode()));
            } finally {
//always save message for user than execute de function
                messageRepository.save(message);
            }

        }   

        @Transactional(readOnly = false, rollbackFor = TeamException.class)
        private void savePlayersA(TeamEntity team) throws TeamException {
            PlayerEntity p1 = new PlayerEntity();
            p1.setName("Name 1");
            p1.setSurname("Surname 1");
            p1.setTeam(team);
            playerService.save(p1);

            PlayerEntity p2 = new PlayerEntity();
            p2.setName("Name 2");
            p2.setSurname("Surname 2");
            p2.setTeam(team);
            playerService.save(p2);
        }

        @Transactional(readOnly = false, rollbackFor = TeamException.class)
        private void savePlayersB(TeamEntity team) throws TeamException {
            PlayerEntity p3 = new PlayerEntity();
            p3.setName("Name 3");
            p3.setSurname("Surname 3");
            p3.setTeam(team);
            playerService.save(p3);

            PlayerEntity p4 = new PlayerEntity();
            p4.setName("Name 4");
            p4.setSurname("Surname 4");
            p4.setTeam(team);
            playerService.save(p4);

            // here something happens and throw my custom exception
            if (true) {
                throw new TeamException("Fail!");
            }
        }   
    }

共有1个答案

杨和蔼
2023-03-14

这不回滚的原因是因为调用事务性方法的异步方法在同一个类中。当您用@transaction或@Async注释方法时,注释代码由Spring创建的代理处理。当被注释的方法像这样在同一个类中时,对它们的调用不能被代理捕获以通过spring处理额外的请求,因此对方法的注释是多余的。您可以通过将savePlayer方法放在一个单独的类中,并在其中使用事务性方法来实现这一点。

 类似资料:
  • 问题内容: 我使用的是Spring 4,我注意到了一个奇怪的行为……如果我从普通实例方法多次调用异步方法,那么它们都将在不同的线程中调用,并在随机时间完成。但是,如果我多次从另一个异步方法中调用一个异步方法,那么它们将按顺序完成。我有这样的事情: 我正在使用默认的异步执行器。我应该换一个吗?但是,该执行程序不会重用任何线程,而是每次都启动另一个线程,因此应该没问题……这仅仅是巧合吗?但是我尝试了十

  • 我正在尝试创建一个事务方法,该方法调用其他几个事务方法以保存一些相互依赖的db实体。如果任何调用失败,我希望事务完全回滚。但是,这不是观察到的行为。这是我的代码: 也有and,但是当事务在第二次调用时失败时,第一个被提交。

  • 问题内容: 在Spring中,带有注释的方法 将获得一个新的事务(如果还没有),但是我注意到,如果从非事务处理方法调用事务方法,则不会获得任何事务。这是代码。 是一个常规方法,该方法调用是事务性的,但不会保留任何更改。 我正在使用Spring 3和Hibernate3。在这里我做错了什么?谢谢。 问题答案: 这是Springs AOP的局限性之一。因为dao bean实际上是在spring时创建的

  • 问题内容: 在Bruce Eckel的“ Thinking In Java,第四版”的第428页(有关类型信息的章节)中,具有以下示例: 也许我有点累,但是我看不到add()方法中对add()的调用是如何工作的。我一直认为它应该有一个引用,或者是一个静态方法(并且我在ArrayList或List中找不到静态add())。我想念什么? 我只是为自己测试,发现这可行: 问题答案: Java为这样的方法

  • 问题内容: 为了了解Spring事务的工作原理,我想知道在以下情况下发生的情况:如果一种方法标记为,而另一种方法标记为。 假设配置使用所有默认设置。 现在,如果我要输入,显然可以开始交易。然后,钻进去会发生什么?交易已经存在的事实会导致没有新的交易诞生,还是我在这里创建两个交易? 关于Propagation的文档(在下面引用)似乎涵盖了这一点,但是我想验证一下我的理解 Propagation:通常