2016-04-06 2 views
0

Ich habe eine nicht transaktionale und asynchrone Methode, die andere transaktionale Methoden desselben Service aufruft.Rollback in der asynchronen Methode, die eine andere transaktionale Methode aufruft

Ich erhalte eine Ausnahme, wenn etwas passiert, wenn etwas passiert, speichere ich den Fehler, aber das Rollback funktioniert nicht.

In diesem Beispiel speichern Sie den Player, um Methoden zum Speichern des Player-Dienstes aufzurufen.

@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 
} 

Mein anderer Service:

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

Warum funktioniert die Rollback? Ich habe den Typ der Ausnahme in der RollbackFor.

Antwort

0

Der Grund dafür ist, dass Ihre asynchrone Methode, die Ihre Transaktionsmethode aufruft, nicht in derselben Klasse liegt. Wenn Sie die Methode mit @Transaction oder @Async annotieren, wird der Annotationscode von dem im Frühjahr erstellten Proxy verarbeitet. Wenn die mit Anmerkungen versehene Methode in derselben Klasse wie diese ist, kann der Aufruf an sie vom Proxy nicht erfasst werden, um die zusätzliche Anforderung über die Feder zu verarbeiten, und daher ist die Anmerkung zur Methode redundant. Sie können dies erreichen, indem Sie die savePlayer-Methoden in einer separaten Klasse verwenden und die Methoden dort transaktional haben.