Spring 批处理:CompositeItemWriter、@BeforeStep 和控制 StepExecution
Spring Batch : CompositeItemWriter, @BeforeStep and Controlling StepExecution
我最近在 spring 批处理中偶然发现了一个非常扭曲的问题。
要求如下:
我有两个主要步骤:
- 第一个从一个oracle数据库读取一些数据,从一个table写到另一个table。
- 第二个基于第一步处理的数据执行一些其他数据库操作。
从设计的角度来看,第一步是这样的:
@Bean
public Step myFirstStep(JdbcCursorItemReader<Revision> reader) {
return stepBuilderFactory.get("my-first-step")
.<Revision, Revision>chunk(1)
.reader(readerRevisionNumber)
.writer(compositeItemWriter())
.listener(executionContextPromotionListener())
.build();
复合项目作者:
@Bean
public CompositeItemWriter<Revision> compositeItemWriter() {
CompositeItemWriter writer = new CompositeItemWriter();
writer.setDelegates(Arrays.asList(somewriter(), someOtherwriter(), aWriterThatIsSupposedToPassDataToAnotherStep()));
return writer;
}
虽然前两位作家并不复杂,但我的兴趣集中在第三位。
aWriterThatIsSupposedToPassDataToAnotherStep()
你可能已经猜到了,这个会用来获取一些之前正在处理的数据,在我的第二步推广:
@Component
@StepScope
public class AWriterThatIsSupposedToPassDataToAnotherStep implements ItemWriter<SomeEntity> {
private StepExecution stepExecution;
public void write(List<? extends SomeEntity> items) {
ExecutionContext stepContext = this.stepExecution.getExecutionContext();
stepContext.put("revisionNumber", items.stream().findFirst().get().getSomeField());
System.out.println("writing : " + items.stream().findFirst().get().getSomeField()+ "to ExecutionContext");
}
@BeforeStep
public void saveStepExecution(StepExecution stepExecution) {
this.stepExecution = stepExecution;
}
}
问题是:只要该作者是复合作者列表的一部分(如上声明)
我最后一个作者的@BeforeStep 从未执行过,这导致我无法将我的信息传输到执行上下文。
在步骤定义中用我的单个“AWriterThatIsSupposedToPassDataToAnotherStep”替换我的 CompositeItemWriter 时,它会正确执行。
它是否必须与某种申报顺序或其他东西做任何事情?
非常感谢进一步的帮助。
找到解决方案(在我的一些同事的帮助下),并来源于:
您需要将编写器声明为复合编写器的一部分,并需要一个步骤侦听器以使其执行带@BeforeStep 注释的方法。
我最近在 spring 批处理中偶然发现了一个非常扭曲的问题。 要求如下:
我有两个主要步骤:
- 第一个从一个oracle数据库读取一些数据,从一个table写到另一个table。
- 第二个基于第一步处理的数据执行一些其他数据库操作。
从设计的角度来看,第一步是这样的:
@Bean
public Step myFirstStep(JdbcCursorItemReader<Revision> reader) {
return stepBuilderFactory.get("my-first-step")
.<Revision, Revision>chunk(1)
.reader(readerRevisionNumber)
.writer(compositeItemWriter())
.listener(executionContextPromotionListener())
.build();
复合项目作者:
@Bean
public CompositeItemWriter<Revision> compositeItemWriter() {
CompositeItemWriter writer = new CompositeItemWriter();
writer.setDelegates(Arrays.asList(somewriter(), someOtherwriter(), aWriterThatIsSupposedToPassDataToAnotherStep()));
return writer;
}
虽然前两位作家并不复杂,但我的兴趣集中在第三位。
aWriterThatIsSupposedToPassDataToAnotherStep()
你可能已经猜到了,这个会用来获取一些之前正在处理的数据,在我的第二步推广:
@Component
@StepScope
public class AWriterThatIsSupposedToPassDataToAnotherStep implements ItemWriter<SomeEntity> {
private StepExecution stepExecution;
public void write(List<? extends SomeEntity> items) {
ExecutionContext stepContext = this.stepExecution.getExecutionContext();
stepContext.put("revisionNumber", items.stream().findFirst().get().getSomeField());
System.out.println("writing : " + items.stream().findFirst().get().getSomeField()+ "to ExecutionContext");
}
@BeforeStep
public void saveStepExecution(StepExecution stepExecution) {
this.stepExecution = stepExecution;
}
}
问题是:只要该作者是复合作者列表的一部分(如上声明) 我最后一个作者的@BeforeStep 从未执行过,这导致我无法将我的信息传输到执行上下文。 在步骤定义中用我的单个“AWriterThatIsSupposedToPassDataToAnotherStep”替换我的 CompositeItemWriter 时,它会正确执行。
它是否必须与某种申报顺序或其他东西做任何事情?
非常感谢进一步的帮助。
找到解决方案(在我的一些同事的帮助下),并来源于:
您需要将编写器声明为复合编写器的一部分,并需要一个步骤侦听器以使其执行带@BeforeStep 注释的方法。