Spring Camel:如果使用者无法确认,则回滚jdbc事务

Spring Camel:如果使用者无法确认,则回滚jdbc事务,spring,jms,apache-camel,activemq,Spring,Jms,Apache Camel,Activemq,我有一个后端应用程序,它使用AMQ/Camel来使用消息。在每个消息处理过程中,使用@TransactionalJDBC DAO完成数据库插入。我配置了两个消息代理 问题是:如果主代理停止,当前的交易所在消费者中会变得过时:其中一些交易所已经进行了插入,但尚未向代理发送ACK。最后,代理将执行消息回滚,然后应用程序再次获取相同的消息,导致数据库错误,因为它们已经插入 如何配置路由,以便在连接中断时尝试回滚?这只有在以编程方式管理事务时才可能吗?首先,DAO上的@Transactional没有意义

我有一个后端应用程序,它使用AMQ/Camel来使用消息。在每个消息处理过程中,使用
@Transactional
JDBC DAO完成数据库插入。我配置了两个消息代理

问题是:如果主代理停止,当前的交易所在消费者中会变得过时:其中一些交易所已经进行了插入,但尚未向代理发送ACK。最后,代理将执行消息回滚,然后应用程序再次获取相同的消息,导致数据库错误,因为它们已经插入


如何配置路由,以便在连接中断时尝试回滚?这只有在以编程方式管理事务时才可能吗?

首先,DAO上的
@Transactional
没有意义。您希望在完成请求后向数据库提交。对于web应用程序,控制器上通常有事务边界。对于JMS使用者,您可以在使用者(或附近)上使用它。这样,您的事务边界就包含了您的业务逻辑和持久化逻辑。一旦线程通过事务边界,该边界的事务管理器将提交(至少在其管理一个资源时,如DB),并且在此之后无法回滚

也就是说,管理具有多个数据源的事务通常是一个困难的问题。在大多数情况下,您会发现使系统能够适应重复消息比同步对多个数据源的提交更容易(例如,保留消息id并在开始处理新消息之前进行查找)

不过,您有一些选择:

  • 当我从JMS数据源消费并持久化到数据库时,我 通常将数据库的事务边界设置为高级别 尽可能在路线上。您可以将
    .transact()
    作为 第一条指令之一,或者更确切地说,您可以标记JMS 消费者使用
    transactided=true
    ,然后挂接事务 提交到数据库的管理器。在提交到数据库时,仍然可能回滚代理,因此需要一些逻辑来处理重复消息
  • 如果您确实希望在提交到代理失败时回滚对数据库的提交,那么您唯一的选择就是使用实现XA事务的事务管理器。这些事务管理器将实现两阶段提交(即1.询问所有资源是否准备好提交,2.提交所有资源。如果阶段1.失败,回滚所有事务)。如果您决定尝试此操作,则必须在camel端点标记事务边界,因为这是您想要提交给代理和数据库的时候
  • XA事务将是一个比处理重复消息更复杂的解决方案,它将需要更多的开发人员。你已经被警告了