我使用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返回重复状态,并且由谁使用此重复状态。 第三,有没有更好的方法可以实现我的目标?
答案 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();
}
希望这会有所帮助。