Heim  >  Artikel  >  Java  >  So lösen Sie das Problem der asynchronen Verwendung von SpringBoot mit Transaktionen

So lösen Sie das Problem der asynchronen Verwendung von SpringBoot mit Transaktionen

WBOY
WBOYnach vorne
2023-05-27 14:37:241245Durchsuche

Ein kürzlich aufgetretenes Szenario bestand darin, dass in einer mit @Transactional annotierten Methode A eine mit einer @Async-Annotation markierte Methode B aufgerufen wurde, da die Transaktion von Methode A nicht festgeschrieben wurde, als Methode B ausgeführt wurde, Methode B jedoch ausgeführt wurde Prozess Die Daten, die in Methode A noch nicht übermittelt wurden, können nicht abgerufen werden, sodass Methode B am Ende abnormal ausgeführt wird.

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

Wie im obigen Code habe ich die Transaktionsanmerkung @Transactional für die Methode zum Erstellen des Benutzers markiert und dann darin die Aktualisierungsmethode update() aufgerufen. Diese Methode wurde mit der Annotation @Async markiert. Obwohl der Code kein Problem zu haben scheint, ist es bei der tatsächlichen Ausführung der update()-Methode möglich, dass die der create()-Methode entsprechende Transaktion noch nicht übermittelt wurde, da sie von anderen Threads ausgeführt wird, und das update( )-Methode kann den neu eingefügten Benutzerdatensatz nicht lesen, was dazu führt, dass die Aktualisierung fehlschlägt.

Lösung

Stellen Sie sicher, dass die Transaktion festgeschrieben wird, bevor Sie die asynchrone Methode aufrufen, indem Sie die Logik anpassen

Der Grund für dieses Problem liegt in der gemeinsamen Verwendung der Annotationen @Transactional und @Async. Dann können wir zunächst in dieser Richtung beginnen Wir können bestätigen, dass nach der Übermittlung der Transaktion der create()-Methode die asynchrone Aktualisierungsmethode ausgeführt wird:

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);
}

Die asynchrone Methode wird außerhalb der Transaktionsmethode aufgerufen, sodass die asynchrone Methode die übermittelten Transaktionsdaten lesen kann.

Wir können TransactionTemplate verwenden, um die @Transactional-Annotation zu ersetzen.

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

Durch die Verwendung von TransactionTemplate zur Unterteilung der Transaktionsgranularität stellen Sie sicher, dass die Transaktion festgeschrieben wurde, bevor Sie die asynchrone Methode aufrufen.

Die oben genannten Lösungen können das Problem grundsätzlich lösen. Im Folgenden finden Sie die von Spring im Internet gefundene Lösung:

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

Durch die Registrierung der asynchronen Methode als Operation nach der Übermittlung der Transaktion kann Spring uns nach der Transaktion automatisch helfen Führen Sie den entsprechenden Vorgang aus.

Das obige ist der detaillierte Inhalt vonSo lösen Sie das Problem der asynchronen Verwendung von SpringBoot mit Transaktionen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen