如何在不使用@StepScope的情况下将JobParameters传递给myBatisPagingItemReader

时间:2019-02-02 12:55:09

标签: spring-batch

我正在使用Spring Batch重新启动功能,以便它从上一个失败的点开始读取。只要不对我的@StepScope bean方法使用myBatisPagingItemReader批注,重新启动就可以正常工作。

我必须使用@StepScope,以便我可以使用myBatisPagingItemReader bean方法的输入参数进行后期绑定以获取jobParameters     @Value("#{JobParameters['run-date']}"))

如果我使用@StepScope,重启将无法进行。

我尝试添加侦听器new JobParameterExecutionContextCopyListener()以将JobParameters复制到ExecutionContext。 但是,由于没有ItemReader的打开方法,我如何在myBatisPagingItemReader中访问ExecutionContext?

不确定在不使用@StepScope的情况下运行myBatisPagingItemReader时如何获得对jobParameters的访问吗?请输入任何内容。

在使用@StepScope时使用新实例(有状态)时,我对spring-batch重新启动的理解是否正确,也不确定。

@Configuration
@EnableBatchProcessing
public class BatchConfig {
    @Bean
    public Step step1(StepBuilderFactory stepBuilderFactory,
        ItemReader<Model> myBatisPagingItemReader,
        ItemProcessor<Model, Model> itemProcessor,
        ItemWriter<Model> itemWriter) {

        return stepBuilderFactory.get("data-load")
            .<Model, Model>chunk(10)
            .reader(myBatisPagingItemReader)
            .processor(itemProcessor)
            .writer(itemWriter)
            .listener(itemReadListener())
             .listener(new JobParameterExecutionContextCopyListener())
            .build();
   }

   @Bean
    public Job job(JobBuilderFactory jobBuilderFactory, @Qualifier("step1") 
               Step step1) {
           return jobBuilderFactory.get("load-job")
            .incrementer(new RunIdIncrementer())
            .start(step1)
            .listener(jobExecutionListener())
            .build();
      }
}

@Component
public class BatchInputReader {

    @Bean
    //@StepScope
    public ItemReader<Model> myBatisPagingItemReader(
             SqlSessionFactory sqlSessionFactory) {
         MyBatisPagingItemReader<Model> reader = new 
         MyBatisPagingItemReader<>();
         Map<String, Object> parameterValues = new HashMap<>();
     // populate parameterValues  from jobParameters ??
         reader.setSqlSessionFactory(sqlSessionFactory);
         reader.setParameterValues(parameterValues);
         reader.setQueryId("query");
         return reader;
    }
 }

2 个答案:

答案 0 :(得分:0)

您要在带有myBatisPagingItemReader@Component)注释的类中声明一个Spring Bean(BatchInputReader)。这是不正确的。

您需要做的是在配置类BatchConfig中将mybatis阅读器声明为bean。完成并用@StepScope注释Bean之后,您可以按以下方式传递传递作业参数:

@Configuration
@EnableBatchProcessing
public class BatchConfig {

    @Bean
    @StepScope
    public ItemReader<Model> myBatisPagingItemReader(
            SqlSessionFactory sqlSessionFactory,
            @Value("#{jobParameters['param1']}") String param1,
            @Value("#{jobParameters['param2']}") String param2) {
        MyBatisPagingItemReader<Model> reader = new
                MyBatisPagingItemReader<>();
        Map<String, Object> parameterValues = new HashMap<>();
        // populate parameterValues  from jobParameters ?? => Those can be now accessed from method parameters
        reader.setSqlSessionFactory(sqlSessionFactory);
        reader.setParameterValues(parameterValues);
        reader.setQueryId("query");
        return reader;
    }

    @Bean
    public Step step1(StepBuilderFactory stepBuilderFactory,
                      ItemReader<Model> myBatisPagingItemReader,
                      ItemProcessor<Model, Model> itemProcessor,
                      ItemWriter<Model> itemWriter) {

        return stepBuilderFactory.get("data-load")
                .<Model, Model>chunk(10)
                .reader(myBatisPagingItemReader)
                .processor(itemProcessor)
                .writer(itemWriter)
                .listener(itemReadListener())
                .listener(new JobParameterExecutionContextCopyListener())
                .build();
    }

    @Bean
    public Job job(JobBuilderFactory jobBuilderFactory, @Qualifier("step1")
            Step step1) {
        return jobBuilderFactory.get("load-job")
                .incrementer(new RunIdIncrementer())
                .start(step1)
                .listener(jobExecutionListener())
                .build();
    }
}

Late Binding of Job and Step Attributes部分中对此有更多详细信息。 BatchInputReader将保留为空,不再需要。少即是多! :-)

希望这会有所帮助。

答案 1 :(得分:0)

添加到我的问题。我已按照建议将myBatisPagingItemReader()添加到配置了注释的类中。

当我对MyBatisPagingItemReader()使用@Stepscope注释时,重新启动示例,读取器正在读取5条记录,并且我将块大小(commit-interval)设置为3。

作业实例-01-作业参数-01/02/2019。
块1:
-流程记录1
-流程记录2
-流程记录3
writer-写全部3条记录
chunk-1提交成功

chunk-2:     处理记录4     流程记录5-引发和异常 作业完成并设置为“失败”状态

现在,使用相同的作业参数再次重新启动作业。
作业实例-01-作业参数-01/02/2019。

块1:
    流程记录1
    流程记录2
    流程记录3
writer-写全部3条记录
chunk-1提交成功

chunk-2:
    流程记录4
    流程记录5-引发和异常
作业完成并设置为“失败”状态

请注意:在这里,当我在myBatisPagingItemReader()bean方法上使用@Stepscope注释时,作业将创建一个新实例,请参见下面的日志消息。
    在scope = step中创建对象,名称= scopedTarget.myBatisPagingItemReader
    在scope = step,name = scopedTarget.myBatisPagingItemReader

中注册的销毁回调 由于它是新实例,因此它从头开始而不是从chunk-2开始。

如果我不使用Stepscope,随着重新启动的作业步骤设置-MyBatisPagingItemReader.read.count = 3,它将从块2重新启动。

我想使用Stepscope使用后期绑定,如果我使用Stepscope,我的myBatisPagingItemReader是否可以从上次失败开始设置read.count以便重新启动工作?


如果我不使用@Stepscope,是否可以在myBatisPagingItemReader中获取作业参数?