假如发送事务消息为SEND_OK,开始执行本地事务
本地事务是业务和事务日志表放一起的,处于一个事务中。
@Transactional
@Override
public void createOrder(OrderDTO orderDTO,String transactionId){
//1.创建订单
Order order = new Order();
BeanUtils.copyProperties(orderDTO,order);
orderMapper.createOrder(order);
//2.写入事务日志
TransactionLog log = new TransactionLog();
log.setId(transactionId);
log.setBusiness("order");
log.setForeignKey(String.valueOf(order.getId()));
transactionLogMapper.insert(log);
logger.info("订单创建完成。{}",orderDTO);
}
@Override
public LocalTransactionState executeLocalTransaction(Message message, Object o) {
createOrder(OrderDTO orderDTO,String transactionId);
.................
}
但是由于spring的事务注解机制,假如你补获了异常,上面的的事务是失效的,就会导致业务成功,日志失败。Rocket源码sendMessageInTransaction()方法是调用你上面的监听方法的并补获了异常的。这是个隐藏的极大隐患问题
//如果发送事务消息状态为send_ok
case SEND_OK:
try {
//执行本地事务方法
if (transactionListener != null) {
this.log.debug("Used new transaction API");
localTransactionState = transactionListener.executeLocalTransaction(msg, arg);
}
} catch (Throwable var10) {
this.log.info("executeLocalTransactionBranch exception", var10);
this.log.info(msg.toString());
localException = var10;
}
break;
解决,重写TransactionMQProducer 实例的sendMessageInTransaction()方法里的这部分方法,手动抛出异常,让spring事务捕获到
try {
//执行本地事务方法
if (transactionListener != null) {
this.log.debug("Used new transaction API");
localTransactionState = transactionListener.executeLocalTransaction(msg, arg);
}
} catch (Throwable var10) {
this.log.info("executeLocalTransactionBranch exception", var10);
this.log.info(msg.toString());
localException = var10;
throw new MQClientException(e.getMessage(),e);
}