[英]How to run a step in a loop in Spring Batch : Updated
我有以下春季批處理工作:
<job id="MyBatchJob" job-repository="jobRepository">
<step id="ConfigurationReadStep">
<tasklet ref="ConfigurationReadTasklet" transaction-manager="jobRepository-transactionManager"/>
<next on="COMPLETED" to="NextStep" />
</step>
<step id="NextStep">
<tasklet transaction-manager="jobRepository-transactionManager">
<chunk reader="myItemReader" writer="myItemWriter" commit-interval="1000"/>
</tasklet>
</step>
<listeners>
<listener ref="jobListener" />
</listeners>
</job>
它的第一步是配置讀取步驟,在經過一些業務邏輯后,我遇到了一系列查詢。 例如說10個查詢。 我知道我可以使用JobExecutionContext
和PromotionListener
來提升此列表。
但是,我想將此查詢作為閱讀器查詢以1對1的方式提供給我的下一步驟的閱讀器,並循環運行該步驟,直到所有閱讀器查詢都被使用為止。 我想將每個查詢作為春季批處理方案運行,因為它們可能返回大量的項目。
我怎樣才能做到這一點 ?
***************************************更新************** ********************
這就是我想要做的:
<job id="MyJob" job-repository="jobRepository">
<step id="ConfigurationReadStep">
<tasklet ref="ConfigurationReadTasklet" transaction-manager="jobRepository-transactionManager"/>
<next on="COMPLETED" to="MyNextStep" />
<listeners>
<listener ref="promotionListener"/>
</listeners>
</step>
<step id="MyNextStep" next="limitDecision">
<tasklet transaction-manager="jobRepository-transactionManager">
<chunk reader="MyItemReader" writer="MyItemWriter" commit-interval="1000"/>
</tasklet>
</step>
<decision id="limitDecision" decider="limitDecider">
<next on="CONTINUE" to="MyNextStep" />
<end on="COMPLETED" />
</decision>
<listeners>
<listener ref="jobListener" />
</listeners>
</job>
<beans:bean id="jobListener" class="com.hsbc.gbm.dml.integration.batch.listener.SimpleJobListener" />
<beans:bean id="promotionListener" class="org.springframework.batch.core.listener.ExecutionContextPromotionListener">
<beans:property name="keys" value="readerLimit,readerQueries,readerSQL" />
</beans:bean>
<beans:bean id="ConfigurationReadTasklet" class="com.mypackage.ConfigurationReadTasklet" scope="step">
</beans:bean>
<beans:bean id="MyItemReader" class="org.springframework.batch.item.database.JdbcCursorItemReader" scope="step">
<beans:property name="dataSource" ref="myDataSource" />
<beans:property name="sql" value="#{jobExecutionContext['readerSQL']}" />
<beans:property name="rowMapper">
<beans:bean name="mapper" class="com.mypackage.MyRowMapper" />
</beans:property>
</beans:bean>
<beans:bean id="MyItemWriter" class="com.mypackage.MyItemWriter" scope="step">
<beans:constructor-arg ref="myDataSource" />
</beans:bean>
<beans:bean id="limitDecider" class="com.mypackage.StepLoopLimitDecider" scope="step">
<beans:property name="readerQueries" value="#{jobExecutionContext['readerQueries']}" />
</beans:bean>
在Tasklet中,我將獲得閱讀器查詢的列表。 我將將readerQuery
設置為其中的第一個,然后轉到下一步,該步驟將作為spring batch步驟正常運行。
完成此操作后,我希望我的Decider
檢查是否有更多讀者查詢,如果可以,它將將readerQuery
更改為下一個查詢,然后重新運行NextStep
,否則作業將完成。 以下是我的決定者:
public class StepLoopLimitDecider implements JobExecutionDecider {
private List<String> readerQueries;
private int count = 1;
public FlowExecutionStatus decide(JobExecution jobExecution,StepExecution stepExecution) {
if (count >= this.readerQueries.size()) {
return new FlowExecutionStatus("COMPLETED");
}
else {
System.out.println(count + ": "+readerQueries.get(count));
jobExecution.getExecutionContext().put("readerSQL", readerQueries.get(count));
count = count + 1;
return new FlowExecutionStatus("CONTINUE");
}
}
public void setReaderQueries(List<String> readerQueries) {
this.readerQueries = readerQueries;
}
}
但是,這不起作用。 步驟在第一次正確運行。 但是決策器失敗,並顯示以下錯誤:
2016-12-06 14:46:24 ERROR AbstractJob:306 - Encountered fatal error executing job
org.springframework.batch.core.JobExecutionException: Flow execution ended unexpectedly
at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:141)
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:281)
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:120)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:48)
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:114)
at org.springframework.batch.core.launch.support.CommandLineJobRunner.start(CommandLineJobRunner.java:348)
at org.springframework.batch.core.launch.support.CommandLineJobRunner.main(CommandLineJobRunner.java:565)
Caused by:
org.springframework.batch.core.job.flow.FlowExecutionException: Ended flow=MyBatchJob at state=MyBatchJob.limitDecision with exception
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:152)
at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:124)
at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:135)
... 6 more
Caused by:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.limitDecider': Scope 'step' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No context holder available for step scope
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:339)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:33)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:182)
at $Proxy4.decide(Unknown Source)
at org.springframework.batch.core.job.flow.support.state.DecisionState.handle(DecisionState.java:43)
at org.springframework.batch.core.configuration.xml.SimpleFlowFactoryBean$DelegateState.handle(SimpleFlowFactoryBean.java:141)
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:144)
... 8 more
Caused by:
java.lang.IllegalStateException: No context holder available for step scope
at org.springframework.batch.core.scope.StepScope.getContext(StepScope.java:197)
at org.springframework.batch.core.scope.StepScope.get(StepScope.java:139)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:325)
... 15 more
有人可以幫我做這個工作嗎?
我建議您根據計算查詢的業務邏輯結果動態地構建您的工作。
但是,您無法使用xml配置進行此操作,因此,建議您使用java-config api。
我對“如何動態創建工作”的類似問題寫了幾個答案。 看看它們,讓我知道,如果您需要更多建議。
Spring Batch Java Config:出現異常時跳過步驟並轉到下一步
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.