@Transactional事务提交后执行异步任务

需求:在插入数据后,查询插入的数据并发送MQ消息

1. @Transactional事务提交后执行异步任务

2. 我们先看一段代码

问题:我们在发送消息时如果事务未提交,此时异步方法中的select(id)方法是查询不到数据的

@Transactional(rollbackFor = Exception.class)
private void A() {
	//插入一条记录
	insert(student);
	sendRabbitMq(student.getId());
}

/**
* 发送Mq消息
*/
@Async
private void sendRabbitMq(String id) {
	Student student = select(id);
	JSON.toJSONString(student);
	String message = rabbitTemplate.convertAndSend(Exchange, "", message);
}

3 . 网上解决方案: TransactionSynchronization接口的afterCommit()方法,最终在事务commit提交后执行。

@Transactional(rollbackFor = Exception.class)
private void A() {
	//插入一条记录
	insert(student);
	if(TransactionSynchronizationManager.isActualTransactionActive()) {
            // 当前存在事务
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
              @Override
              public void afterCommit() {
                executor.execute(() -> {
                Student student = select(id);
				JSON.toJSONString(student);
				String message = rabbitTemplate.convertAndSend(Exchange, "", message);
                //........
                });
              }});
        } else {
            // 当前不存在事务
            executor.execute(() -> {
            Student student = select(id);
			JSON.toJSONString(student);
			String message = rabbitTemplate.convertAndSend(Exchange, "", message);
                });
        }
}

4. 最终解决方案:因为需要用到线程池,所以在网上方案上进行部分修改 因为@Async注解修饰的方法是无法获取TransactionSynchronizationManager的 所以通过增加一个方法,在这个方法中获取事务管理器并调用多线程方法

@Transactional(rollbackFor = Exception.class)
private void A() {
	//插入一条记录
	insert(student);
	sendRabbitMq(student.getId());
}

/**
* 用于获取事务处理器
*/
private void sendRabbitMq(String id) {
// 注册事务同步处理
		if (TransactionSynchronizationManager.isActualTransactionActive()) {
			//存在事物
			TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
				@Override
				public void afterCommit() {
					sendRabbitMqAsync(String id)
				}
			});
		} else {
			sendRabbitMqAsync(String id)
		}
}


/**
* 进行发送数据操作
*/
@Async("rabbitMqExecutor")
private void sendRabbitMqAsync(String id) {
	Student student = select(id);
	JSON.toJSONString(student);
	String message = rabbitTemplate.convertAndSend(Exchange, "", message);
}

注意:方法A不能调用同一给类中使用了@Async注解的方法B(此时@Async会失效)

参考资料

  1. Spring使用TransactionalEventListener解决事务未提交读取不到数据问题
  2. @Transactional事务提交后触发异步方法
  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值