簡體   English   中英

異步方法中的回滾,該方法調用另一個事務方法

[英]Rollback in async method that calls another transactional method

我有一個非事務和異步方法,該方法調用同一服務的其他事務方法。

如果發生某些事情,我會捕獲異常,如果發生某些事情,我會保存錯誤,但回滾不起作用。

在此示例中,要調用播放器服務的保存方法,事務將保存播放器。

@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方法並在那里進行事務處理來實現。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM