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自然无法识别到异常,更遑论要正确回滚事务了。
所以这个问题可以有两个解决方案:
- 不要吞掉执行过程中的异常,去掉try catch或者catch后再重新throw出去
- 将同一事务的操作都封装到另外一个Service的方法中,在消费时,调用封装好的方法
参考资料
https://docs.spring.io/spring...
以上是 Springboot-Rabbitmq消费者端执行sql异常回滚问题 的全部内容, 来源链接: utcz.com/p/944537.html