Un scénario que j'ai rencontré récemment était qu'une méthode B marquée par l'annotation @Async était appelée dans une méthode A annotée avec @Transactional Parce que la transaction de la méthode A n'était pas validée lors de l'exécution de la méthode B, mais que la méthode B était en cours d'exécution. processus. Les données non soumises dans la méthode A ne peuvent pas être obtenues, donc à la fin, la méthode B s'exécute anormalement.
@Transactional public void create(User user){ // 如果用户已存在,则先删除 delete(user.id); // 创建用户 int userId = insert(user); // 更新用户信息 update(userId); } @Async public void update(Integer userId){ Icon icon = getUserIcon(userId); // 更新用户图片 updateUserPohot(userId,icon); }
Comme le code ci-dessus, j'ai marqué l'annotation de transaction @Transactional sur la méthode de création de l'utilisateur, puis j'ai appelé la méthode de mise à jour update(). Cette méthode a été marquée avec l'annotation @Async. Bien que le code ne semble poser aucun problème, lorsque la méthode update() est effectivement exécutée, car elle est exécutée par d'autres threads, il est possible que la transaction correspondant à la méthode create() n'ait pas encore été soumise et que la méthode update( ) ne peut pas le lire. L'enregistrement utilisateur nouvellement inséré est obtenu, ce qui entraîne l'échec de la mise à jour.
Assurez-vous que la transaction est validée avant d'appeler la méthode asynchrone en ajustant la logique
La raison de ce problème est due à l'utilisation des annotations @Transactional et @Async ensemble, alors nous pouvons commencer par cette direction, d'abord nous pouvons confirmer Après avoir soumis la transaction de la méthode create(), puis exécutez la méthode de mise à jour asynchrone :
public void create(User user){ int userId = doCreate(user); // 更新用户信息 update(userId); } @Transactional public void doCreate(User user){ // 如果用户已存在,则先删除 delete(user.id); // 创建用户 return insert(user); } @Async public void update(Integer userId){ Icon icon = getUserIcon(userId); // 更新用户图片 updateUserPohot(userId,icon); }
La méthode asynchrone est appelée en dehors de la méthode de transaction, afin que la méthode asynchrone puisse lire les données de transaction soumises.
Nous pouvons utiliser TransactionTemplate pour remplacer l'annotation @Transactional
@Autowired TransactionTemplate transactionTemplate; public void create(User user){ int userId = transactionTemplate.execute(status->{ // 如果用户已存在,则先删除 delete(user.id); // 创建用户 return insert(user); }); // 更新用户信息 update(userId); } @Async public void update(Integer userId){ Icon icon = getUserIcon(userId); // 更新用户图片 updateUserPohot(userId,icon); }
En utilisant TransactionTemplate pour subdiviser la granularité de la transaction, assurez-vous que la transaction a été validée avant d'appeler la méthode asynchrone.
Les solutions ci-dessus peuvent essentiellement résoudre le problème. Voici la solution proposée par Spring trouvée sur Internet :
@Transactional public void create(User user){ // 如果用户已存在,则先删除 delete(user.id); // 创建用户 int userId = insert(user); TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { @Override public void afterCommit() { // 更新用户信息 update(userId); } }); } @Async public void update(Integer userId){ Icon icon = getUserIcon(userId); // 更新用户图片 updateUserPohot(userId,icon); }
En enregistrant la méthode asynchrone en tant qu'opération après la soumission de la transaction, Spring peut automatiquement nous aider une fois la transaction terminée. soumis. Effectuez l’opération correspondante.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!