Java 当Spring批处理管理事务回滚时重试不工作

Java 当Spring批处理管理事务回滚时重试不工作,java,spring-boot,spring-batch,spring-retry,Java,Spring Boot,Spring Batch,Spring Retry,在Spring批处理作业的其中一个步骤中,我尝试对其进行配置,以便在发生ObjectOptimisticLockingFailureException时,可以重试该步骤,并希望重试能够起作用 @Bean public Step myStep(StaxEventItemReader<Response> staxEventResponseReader, ItemWriter<Response> itemWriter, ItemProcessor

在Spring批处理作业的其中一个步骤中,我尝试对其进行配置,以便在发生
ObjectOptimisticLockingFailureException
时,可以重试该步骤,并希望重试能够起作用

  @Bean
  public Step myStep(StaxEventItemReader<Response> staxEventResponseReader,
      ItemWriter<Response> itemWriter,
      ItemProcessor<? super Response, ? extends Response> responseProcessor) {
    return stepBuilderFactory.get("myStep")
        .<Response, Response>chunk(1)
        .reader(staxEventResponseReader)
        .processor(responseProcessor)
        .writer(itemWriter)
        //.faultTolerant().retryLimit(3).retry(Exception.class)
        .build();
  }
当我试图在我的writer中显式抛出
ObjectOptimisticLockingFailureException
时,重试逻辑如预期般完美地工作。我的问题是:

  • 如果在步骤中我的编写器代码没有抛出异常,而是在SpringBatch提交区块事务时抛出异常,那么如何使重试逻辑工作
  • 另一个奇怪的行为是,当我通过碰撞数据库中的version列手动导致
    ObjectOptimisticLockingFailureException
    ,并且在步骤中注释了重试定义时,步骤的最终状态是预期的失败。但在未注释重试定义的情况下,该步骤的最终状态为“完成”。为什么呢
  • 如果在步骤中我的编写器代码没有抛出异常,而是在SpringBatch提交区块事务时抛出异常,那么如何使重试逻辑工作
  • 这里有一个尚未解决的问题:。解决方法是(尝试预测并)抛出编写器中提交时可能发生的任何异常。这是您已经尝试过并确认有效的方法,当您说
    时,当我试图在我的writer中显式抛出ObjectOptimisticLockingFailureException时,重试逻辑如预期的那样完美地工作了

  • 另一个奇怪的行为是,当我通过碰撞数据库中的version列手动导致ObjectOptimisticLockingFailureException时,在步骤中注释了重试定义,步骤的最终状态是预期的失败。但在未注释重试定义的情况下,该步骤的最终状态为“完成”。为什么呢

  • 这与上一个问题有关,但由另一个问题引起:。也就是说,在调试会话期间使用
    version
    字段可以理解事情的工作原理,但我不建议更改代码中的
    version
    列。此列上的Spring Batch严重采用了乐观锁定策略,预计不会在用户代码中更改此列的值,否则可能会发生意外行为。

    谢谢@Mahmoud Ben Hassine!解决办法奏效了。我所需要做的就是调用
    entityManager.flush()在更新之后(如您所说,预测异常),而
    ObjectOptimisticLockingFailureException
    将直接在此行抛出。关于手动
    版本
    字段更改,这只是复制异常的更快方法。我曾经在另一个应用程序中设置一个断点,它可以通过其他一些更新触及同一行,并让该事务首先完成。感谢提醒我们不要直接在代码中使用
    version
    字段。我只想指出的是,在解决方法中,我不再看到第二个问题的行为。欢迎您的帮助<代码>我需要做的就是调用entityManager.flush()
    。对于JPA,是的,这是此处建议的解决方法:。事实上,它在这两个问题上都起作用。
    Chunk Transaction Begin
        Begin Retry loop in FaultTolerantChunkProcessor.write()
            Writer logic in my Step
        End Retry loop
    Chunk Transaction Commit - Throws ObjectOptimisticLockingFailureException