从文件中加载春季批次中的参考数据

时间:2017-09-08 19:00:09

标签: spring spring-batch

我想从输入文件(CSV)预加载一些参考数据作为初始步骤之一(预加载引用)。以下步骤将读取包含需要处理的数据的主输入文件。要处理的每个记录都需要在preload-references步骤中加载lookkup数据。如何才能做到这一点?!参考数据可以与数据记录一起传递到主处理器例程吗?

2 个答案:

答案 0 :(得分:0)

为简单起见 - 我们可以假设你需要一个有两个步骤的工作,第一步是将数据传递给第二步吗?如果是这种情况,您可以尝试:

  1. 将数据存储到步骤1的ExecutionContext
  2. "促进"借助ExecutionContextPromotionListener
  3. 将此数据导入下一步
  4. 将数据用于第二步。
  5. 我会用一个部分受official documentation启发的非常天真的例子来支持我的话语。

    在第一步中,我们正在阅读"值:

    class Step1Reader implements ItemReader<String> {
    
      private AtomicLong counter = new AtomicLong();
    
      @Override
      public String read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
    
        long cnt = counter.incrementAndGet();
    
        return cnt > 5 ? null : String.valueOf(cnt);
      }
    }
    

    然后&#34;处理&#34;他们通过在最后添加当前时间毫秒:

    class Step1Processor implements ItemProcessor<String, String> {
    
      @Override
      public String process(String item) throws Exception {
    
        return item + "~" + System.currentTimeMillis();
      }
    }
    

    最后将它们输出到标准输出中并在上下文中存储一些垃圾(我将忽略多线程问题):

    class Step1Writer implements ItemWriter<String> {
    
      private StepExecution stepExecution;
    
      @Override
      public void write(List<? extends String> items) throws Exception {
        items.forEach(System.out::println);
        Integer hashCode = (Integer)stepExecution.getExecutionContext().get("key");
        stepExecution.getExecutionContext().put("key", hashCode == null ? items.hashCode() : hashCode + items.hashCode());
      }
    
      @BeforeStep
      public void saveStepExecution(StepExecution stepExecution) {
        this.stepExecution = stepExecution;
      }
    }
    

    这应输出如下内容:

    1~1505055135727
    2~1505055135727
    3~1505055135727
    4~1505055135727
    5~1505055135727
    

    到目前为止一切顺利。下一步是&#34;促进&#34;关键:

      @Bean
      ExecutionContextPromotionListener executionContextPromotionListener()
      {
        ExecutionContextPromotionListener ret = new ExecutionContextPromotionListener();
        ret.setKeys(new String[]{"key"});
        return ret;
      }
    
      private Step step1() {
        return stepBuilderFactory.get("step1")
            .<String, String> chunk(10)
            .reader(new Step1Reader())
            .processor(new Step1Processor())
            .writer(new Step1Writer())
            .listener(promotionListener)
            .build();
      }
    

    在第二个甚至更天真的步骤中,可以像这样访问该值:

    class Step2Writer  implements ItemWriter<String> {
    
      private Object obj;
    
      @Override
      public void write(List<? extends String> items) throws Exception {
        items.forEach(s -> System.out.println(s + "~" + obj));
      }
    
      @BeforeStep
      public void retrieveInterstepData(StepExecution stepExecution) {
        JobExecution jobExecution = stepExecution.getJobExecution();
        ExecutionContext jobContext = jobExecution.getExecutionContext();
        this.obj = jobContext.get("key");
      }
    }
    

    希望有所帮助: - )

答案 1 :(得分:0)

不推荐将大量数据存储到StepExecutionContext中,因为此上下文被序列化为SB元数据表,如果数据太大,您将收到数据截断错误。 您可以使用特定的DAO访问此数据,而不是预加载数据,并将访问请求置于缓存下:无需减慢预加载速度,内存消耗将根据您的工作增长。 您还将获得可重启性。