【问题标题】:Spring Integration - rollback second transaction if first transaction failsSpring Integration - 如果第一个事务失败,则回滚第二个事务
【发布时间】:2019-02-09 12:53:47
【问题描述】:

我必须将数据保存到 2 个不同的表中。我需要它是全有或全无的交易。如果第二个事务失败,如何回滚第一个事务?

在下面的代码中,我storeToTable1(),storeToTable2()都是按这个顺序执行的。

如果 storeToTable2() 失败,我希望 storeToTable1() 回滚。

配置类:

class StoreToDBConfig {
    @Bean
        public IntegrationFlow receiveMessage() {
            return IntegrationFlows
                    .from("inputChannel")
                    .transform("convertToTable1Format")
                    .handle(ServicetoDBAdaptor,"storeToTable1")
                    .transform("convertToTable2Format")
                    .handle(ServicetoDBAdaptor,"storeToTable2")
                    .get();                 
        }
}

数据库适配器服务:

class ServicetoDBAdaptor {

@Autowired
UserExecutionDetail userExecutionDetail;

@Autowired
UserExecution userExecution;

@Autowired
UserExecutionDetailRepository userExecutionDetailRepository;

@Autowired
UserExecutionRepository userExecutionRepository;

@Transactional(propagation=Propagation.REQUIRED)
@ServiceActivator
private void storeToTable1(Message<UserExecutionDetail> msg) throws Exception {
    userExecutionDetailRepository.save(msg.getPayload());
}

@Transactional(propagation=Propagation.REQUIRED)
@ServiceActivator
private void storeToTable2(Message<UserExecution> msg) throws Exception {
    userExecutionRepository.save(msg.getPayload());
}
}

【问题讨论】:

    标签: transactions spring-data-jpa spring-integration


    【解决方案1】:

    为此,您需要在第一个 handle() 上使用如下内容:

    .handle(ServicetoDBAdaptor,"storeToTable1", e -> e.transactional(true))
    

    这个钩子会做这个:

    /**
     * Specify a {@link TransactionInterceptor} {@link Advice} with default
     * {@code PlatformTransactionManager} and {@link DefaultTransactionAttribute} for the
     * {@link MessageHandler}.
     * @param handleMessageAdvice the flag to indicate the target {@link Advice} type:
     * {@code false} - regular {@link TransactionInterceptor}; {@code true} -
     * {@link org.springframework.integration.transaction.TransactionHandleMessageAdvice}
     * extension.
     * @return the spec.
     */
    public S transactional(boolean handleMessageAdvice) {
    

    我们将在哪里使用这个:

    /**
     * A {@link TransactionInterceptor} extension with {@link HandleMessageAdvice} marker.
     * <p>
     * When this {@link Advice} is used from the {@code request-handler-advice-chain}, it is applied
     * to the {@link MessageHandler#handleMessage}
     * (not to the
     * {@link org.springframework.integration.handler.AbstractReplyProducingMessageHandler.RequestHandler#handleRequestMessage}),
     * therefore the entire downstream process is wrapped to the transaction.
     * <p>
     * In any other cases it is operated as a regular {@link TransactionInterceptor}.
     *
     * @author Artem Bilan
     *
     * @since 5.0
     */
    @SuppressWarnings("serial")
    public class TransactionHandleMessageAdvice extends TransactionInterceptor implements HandleMessageAdvice {
    

    这里的关键技巧是the entire downstream process is wrapped to the transaction.

    因此,交易将从您的storeToTable1() 开始,并将扩大到流程结束,您的storeToTable2() 将参与同一个交易。因此,当该回滚时,第一个也将回滚。仅仅因为您将只有一次交易!

    【讨论】:

      猜你喜欢
      • 2019-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-25
      • 1970-01-01
      相关资源
      最近更新 更多