SpringBoot事务提交后执行后续操作

sprintboot transaction after commit

Posted by alovn on June 24, 2019

业务要求

  • 操作A操作数据库失败后,事务回滚,那么操作B不能执行。
  • 操作A执行成功后,操作B若失败,B需要回滚,A不需要回滚。

实现方案

使用TransactionSynchronizationManager在事务提交之后操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@Component
public class TransactionCallBackService {

    public void execute(final TransactionCallBackAction action) {

        if (TransactionSynchronizationManager.isActualTransactionActive()) {
            TransactionSynchronizationManager
                    .registerSynchronization(new TransactionSynchronizationAdapter() {
                        @Override
                        public void afterCommit() {
                            // 事务提交后执行回调
                            action.callback();
                        }
                    });
        } else {
            // 事务提交后执行回调
            action.callback();
        }

    }

}

public interface TransactionCallBackAction {
    /**
     * 普通事务回调
     */
    void callback();
}

有了上述两个类,就可以实现在一个事务提交后将消息发送到队列或是其他操作,具体操作如下

假设在一个业务下,数据库插入了一条记录后,再插入另外一条记录:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Override
@Transactional(rollbackFor = Exception.class)
public void save() {
    User user = new User();
    userMapper.insert(user);
    // 在事务提交后执行
    transactionCallBackService.execute(() -> {
        // ...
        logService.insertLog()
    });
}

@Overvide
@Transactional(rollbackFor = Exception.class, propagation=Propagation.REQUIRES_NEW)
public void insertLog() {
    // ...
    //Log
}

REQUIRES_NEW 开启一个新的事务, 经过测试 REQUIRES_NEW 需要在不同的 service 中才会生效。