重复执行tasklet步骤,直到达到特定条件

时间:2019-01-28 02:14:51

标签: spring-batch spring-batch-tasklet

我使用Spring批处理来构建ETL作业。我的主要工作只是从数据库读取并写入另一个数据库。在执行主要工作之前,我需要检查源数据库中的状态以查看其是否准备就绪。仅当源数据库准备就绪时,我才继续进行主要作业。我将检查状态逻辑实现为Tasklet,并使用简单的逻辑来构建我的工作,如果检查状态步骤失败,则重复此步骤,直到成功为止,然后继续执行主要作业。我的工作如下:

@Bean
public Job myJob(MyListener listener) {

    return jobBuilderFactory.get(jobName)
                            .incrementer(new RunIdIncrementer())
                            .listener(listener)
                            .start(checkStatusStep())
                            .on("*").to(mainStep())
                            .on(ExitStatus.FAILED.getExitCode())
                            .to(checkStatusStep())
                            .end()
                            .build();
}

检查状态步骤是一个Tasklet,如下所示:

@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws InterruptedException {
    //isReady method check the db to see if it is ready
    if (isReady()) {
        //contribution.setExitStatus(ExitStatus.COMPLETED);
        return RepeatStatus.FINISHED;
    } else {
        //contribution.setExitStatus(ExitStatus.FAILED);
        return RepeatStatus.CONTINUABLE;
    }
}

我阅读了Spring批处理文档,并获得了条件跟踪中的ON方法将检查步骤的退出状态,以便在StepContribution中设置退出状态。使我感到困惑的是,当我注释掉这两行并且代码仍然有效时。

所以我的问题是,首先,如果条件流程检查了退出状态,为什么我的代码可以在不显式更改退出状态的情况下工作?其次,为什么tasklet返回重复状态,并且由谁使用此重复状态。 第三,有没有更好的方法可以实现我的目标?

1 个答案:

答案 0 :(得分:1)

  

如果条件流检查了退出状态,为什么我的代码可以在不显式更改退出状态的情况下工作?

由于默认情况下,如果小任务返回RepeatStatus.FINISHED,则其退出代码将设置为COMPLETED

  

第二,为什么tasklet返回重复状态,重复对象由谁使用。

TaskletStep反复调用tasklet,直到它返回RepeatStatus.FINISHED或引发异常以表明失败。对Tasklet的每次调用都包装在一个事务中。因此,该结构是具有事务边界的循环结构。

  

第三,有没有更好的方法可以实现我的目标?

IMO,您的Tasklet实现是可以的,您不需要退出状态。像这样:

@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws InterruptedException {
   //isReady method check the db to see if it is ready
   if (isReady()) {
    return RepeatStatus.FINISHED;
   } else {
    return RepeatStatus.CONTINUABLE;
   }
}

这将连续运行,直到isReady为真为止,因此您不需要在作业级别使用流来实现迭代。职位定义为:

@Bean
public Job myJob(MyListener listener) {

   return jobBuilderFactory.get(jobName)
                        .incrementer(new RunIdIncrementer())
                        .listener(listener)
                        .start(checkStatusStep())
                        .next(mainStep())
                        .build();
}

希望这会有所帮助。