Springboot-Rabbitmq消费者端执行sql异常回滚问题

尊敬的大佬们:

小弟初学springboot 集成 rabbitmq,遇到了一个问题,就是关于rabbitmq消费端异常回滚问题。

比如: 我们下了一个订单,把相关业务放到rabbitmq消费端处理,现在同时需要处理2个事件,第一需要修改订单状态,第二需要修改用户的余额,在springboot里我们可以使用@Transactional可以保证以上两点同时修改才算完成,但是在rabbitmq消费端@Transactional就失效了,导致比如第一部修改状态完成,中间出现了异常,第二部修改用户余额的操作就没有进行。求解,怎么在rabbitmq消费者端实现sql执行的回滚操作。代码如下:

  @Transactional(rollbackFor = Exception.class)

@RabbitListener(queues = Demo.DELAYED_QUEUE)

public void delayedQueueReceiver(Map map, Message message, Channel channel) throws IOException {

try {

Test test1 = new Test();

testMapper.insert(test1);

L.error("插入-" + test1.getDid());

int i = 1 / 0; //处理出现异常

Test test2 = new Test();

testMapper.insert(test2);

L.error("插入-" + test2.getDid());

} catch (Exception e) {

L.error("发生了异常" + e.getMessage());

e.printStackTrace();

}

channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);

}

以上代码,导致test2失败,test1成功,我希望如果test2失败,哪test1也不执行。


回答:


回答:

这个问题涉及到Spring声明式事务的实现原理,简略的说,Spring会通过AOP机制为被@Transactional注解标记的类或方法生成代理,在代理中完成事务的管控(提交、回滚等)等工作,以Spring官方文档的一张图来表示如下:

上图中,事务的回滚是发生在Transaction Advisor中的,如果我们在自己的方法(Target Method)中就把异常给吞掉,那Transaction Advisor自然无法识别到异常,更遑论要正确回滚事务了。

所以这个问题可以有两个解决方案:

  1. 不要吞掉执行过程中的异常,去掉try catch或者catch后再重新throw出去
  2. 将同一事务的操作都封装到另外一个Service的方法中,在消费时,调用封装好的方法

参考资料
https://docs.spring.io/spring...

以上是 Springboot-Rabbitmq消费者端执行sql异常回滚问题 的全部内容, 来源链接: utcz.com/p/944537.html

回到顶部