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.
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!