Maison > Java > javaDidacticiel > Comment résoudre le problème de l'utilisation asynchrone de SpringBoot avec les transactions

Comment résoudre le problème de l'utilisation asynchrone de SpringBoot avec les transactions

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
Libérer: 2023-05-27 14:37:24
avant
1324 Les gens l'ont consulté

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);
}
Copier après la connexion

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.

Solution

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);
}
Copier après la connexion

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);
}
Copier après la connexion

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);
}
Copier après la connexion

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!

Étiquettes associées:
source:yisu.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal