业务要求
- 操作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 中才会生效。