SpringBoot事務(wù)提交后執(zhí)行后續(xù)操作
業(yè)務(wù)場景
業(yè)務(wù)需求上經(jīng)常會有一些邊緣操作,比如主流程操作A:用戶報名課程操作入庫,邊緣操作B:發(fā)送郵件或短信通知。
業(yè)務(wù)要求
- 操作A操作數(shù)據(jù)庫失敗后,事務(wù)回滾,那么操作B不能執(zhí)行。
- 操作A執(zhí)行成功后,操作B也必須執(zhí)行成功
如何實現(xiàn)
- 普通的執(zhí)行A,之后執(zhí)行B,是可以滿足要求1,對于要求2通常需要設(shè)計補償?shù)牟僮?/li>
- 一般邊緣的操作,通常會設(shè)置成為異步的,以提升性能,比如發(fā)送MQ,業(yè)務(wù)系統(tǒng)負責(zé)事務(wù)成功后消息發(fā)送成功,然后接收系統(tǒng)負責(zé)保證通知成功完成
實現(xiàn)方案
使用TransactionSynchronizationManager在事務(wù)提交之后操作
@Component
public class CallBackService {
public void execute(final CallBackAction action) {
if (TransactionSynchronizationManager.isActualTransactionActive()) {
TransactionSynchronizationManager
.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
// 事務(wù)提交后執(zhí)行回調(diào)
action.callback();
}
});
} else {
// 事務(wù)提交后執(zhí)行回調(diào)
action.callback();
}
}
}
public interface CallBackAction {
/**
* 普通事務(wù)回調(diào)
*/
void callback();
}
有了上述兩個類,就可以實現(xiàn)在一個事務(wù)提交后將消息發(fā)送到隊列或是其他操作,具體操作如下
假設(shè)在一個業(yè)務(wù)下,往數(shù)據(jù)庫插入了一條記錄,然后向隊列發(fā)送一條消息
@Override
@Transactional()
public void save() {
User user1 = new User();
User user2 = new User();
userMapper.insert(user1);
userMapper.insert(user2);
// 在事務(wù)提交后執(zhí)行
callBackService.execute(() -> {
// ...
});
}