java - 调用另一个事务方法的异步方法中的回滚

标签 java spring asynchronous transactions

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

如果发生某些情况,我会捕获异常,如果发生某些情况,我会保存错误,但回滚不起作用。

在本例中,调用Player服务的save方法,事务保存了玩家。

@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!");
            }
        }   
    }

为什么不回滚?我把异常的类型放在rollbackFor中。

最佳答案

这不会为您回滚的原因是因为调用事务方法的异步方法位于同一个类中。当您使用@Transaction或@Async注释方法时,注释代码由spring创建的代理处理。当像这样注释的方法位于同一个类中时,代理无法捕获对它们的调用来通过 spring 处理额外的请求,因此方法上的注释是多余的。您可以通过将 savePlayer 方法放在单独的类中并在那里使用事务方法来解决此问题。

关于java - 调用另一个事务方法的异步方法中的回滚,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36460838/

相关文章:

java - 如何将运行无限循环的线程限制为1个核心?

java - Spring 的数据绑定(bind)器 autoGrowCollectionLimit 不能正常工作

spring - 在 Spring Boot 应用程序中禁用表重新创建

java - 如何在登录页面上确定是否有用户已经登录?

javascript - Node.js + Express 应用程序中的并发如何工作?

c# - 事件对象模式的 .NET 实现

javascript - AngularJS:从函数返回数据并将其分配给变量

java - Spring .jar 未启动

java - playframework 每天用 Akka 运行任务

java - 使用java将xls中的字符串转换为日期格式