将数据从 Partitioner 传递到 JdbcCursorItemReader
Pass data from Partitioner to JdbcCursorItemReader
我正在尝试将 sping batch Partitioner 用于我的块处理步骤。我想使用 stepexecutioncontext 将数据从 Partitioner 传递到我的 itemreader 步骤,但无法这样做。
以下是我的配置-
分区程序-
public class MyPartitioner implements Partitioner{
@Override
public Map<String, ExecutionContext> partition(int gridSize)
{
Map<String, ExecutionContext> partitionMap = new HashMap<String, ExecutionContext>();
List<String> codes = getCodes();
for (String code : codes)
{
ExecutionContext context = new ExecutionContext();
context.put("code", code);
partitionMap.put(code, context);
}
return partitionMap;
}}
工作config.xml-
<bean id="MyPartitioner" class="com.MyPartitioner" />
<bean id="itemProcessor" class="com.MyProcessor" scope="step" />
<bean id="itemReader" class="org.springframework.batch.item.database.JdbcCursorItemReader" scope="step" >
<property name="dataSource" ref="dataSource"/>
<property name="sql" value="select * from mytable WHERE code = '#{stepExecutionContext[code]}' "/>
<property name="rowMapper">
<bean class="com.MyRowMapper" scope="step"/>
</property>
</bean>
<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor" >
<property name="corePoolSize" value="20"/>
<property name="maxPoolSize" value="20"/>
<property name="allowCoreThreadTimeOut" value="true"/>
</bean>
<bean id="itemWriter" class="org.springframework.batch.item.database.JdbcBatchItemWriter" scope="step">
<property name="dataSource" ref="dataSource"/>
<property name="sql" value="some sql" />
<property name="itemSqlParameterSourceProvider">
<bean class="org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider"/>
</property>
</bean>
<batch:step id="Step1" xmlns="http://www.springframework.org/schema/batch">
<batch:tasklet transaction-manager="transactionManager">
<batch:chunk reader="itemReader" processor="itemProcessor" writer="itemWriter" commit-interval="200"/>
</batch:tasklet>
</batch:step>
<batch:job id="myjob">
<batch:step id="mystep">
<batch:partition step="Step1" partitioner="MyPartitioner">
<batch:handler grid-size="20" task-executor="taskExecutor"/>
</batch:partition>
</batch:step>
</batch:job>
当 运行 作为独立应用程序时,此代码工作正常,但当 运行 在服务器应用程序中时,itemreader 步骤将查询读取为
select * 来自 mytable WHERE code = '#{stepExecutionContext[code]}' 而不是
select * 来自 mytable WHERE code = 'mycode'.
请告诉我我做错了什么,或者是否需要进行任何其他配置才能在服务器应用程序中运行?
谢谢
您可以设置自己的 class,扩展 JdbcCursorItemReader
,使其成为 @StepScope
并添加 @BeforeStep
。
@BeforeStep
public void beforeStep(final StepExecution stepExecution) {
final String code = execution.getExecutionContext().getString("code");
final String sql = buildSql(code); //method which creates sql statement
}
其中有 StepExecution
,您可以获取需要的变量,这些变量在上下文中用于构建 sql。覆盖 afterPropertiesSet()
以设置 sql
、rowMapper
和 dataSource
。
@Override
public void afterPropertiesSet() throws Exception {
setSql(sql);
setRowMapper(rowMapper);
setDataSource(dataSource);
super.afterPropertiesSet();
}
使用 java 代码而不是 xml 应该始终是 IMO 首选方法,因为您手头有代码,您可以进行调试,这样可以避免潜在的 xml 键入错误。该方法也是可测试的。
我正在尝试将 sping batch Partitioner 用于我的块处理步骤。我想使用 stepexecutioncontext 将数据从 Partitioner 传递到我的 itemreader 步骤,但无法这样做。
以下是我的配置-
分区程序-
public class MyPartitioner implements Partitioner{
@Override
public Map<String, ExecutionContext> partition(int gridSize)
{
Map<String, ExecutionContext> partitionMap = new HashMap<String, ExecutionContext>();
List<String> codes = getCodes();
for (String code : codes)
{
ExecutionContext context = new ExecutionContext();
context.put("code", code);
partitionMap.put(code, context);
}
return partitionMap;
}}
工作config.xml-
<bean id="MyPartitioner" class="com.MyPartitioner" />
<bean id="itemProcessor" class="com.MyProcessor" scope="step" />
<bean id="itemReader" class="org.springframework.batch.item.database.JdbcCursorItemReader" scope="step" >
<property name="dataSource" ref="dataSource"/>
<property name="sql" value="select * from mytable WHERE code = '#{stepExecutionContext[code]}' "/>
<property name="rowMapper">
<bean class="com.MyRowMapper" scope="step"/>
</property>
</bean>
<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor" >
<property name="corePoolSize" value="20"/>
<property name="maxPoolSize" value="20"/>
<property name="allowCoreThreadTimeOut" value="true"/>
</bean>
<bean id="itemWriter" class="org.springframework.batch.item.database.JdbcBatchItemWriter" scope="step">
<property name="dataSource" ref="dataSource"/>
<property name="sql" value="some sql" />
<property name="itemSqlParameterSourceProvider">
<bean class="org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider"/>
</property>
</bean>
<batch:step id="Step1" xmlns="http://www.springframework.org/schema/batch">
<batch:tasklet transaction-manager="transactionManager">
<batch:chunk reader="itemReader" processor="itemProcessor" writer="itemWriter" commit-interval="200"/>
</batch:tasklet>
</batch:step>
<batch:job id="myjob">
<batch:step id="mystep">
<batch:partition step="Step1" partitioner="MyPartitioner">
<batch:handler grid-size="20" task-executor="taskExecutor"/>
</batch:partition>
</batch:step>
</batch:job>
当 运行 作为独立应用程序时,此代码工作正常,但当 运行 在服务器应用程序中时,itemreader 步骤将查询读取为
select * 来自 mytable WHERE code = '#{stepExecutionContext[code]}' 而不是
select * 来自 mytable WHERE code = 'mycode'.
请告诉我我做错了什么,或者是否需要进行任何其他配置才能在服务器应用程序中运行?
谢谢
您可以设置自己的 class,扩展 JdbcCursorItemReader
,使其成为 @StepScope
并添加 @BeforeStep
。
@BeforeStep
public void beforeStep(final StepExecution stepExecution) {
final String code = execution.getExecutionContext().getString("code");
final String sql = buildSql(code); //method which creates sql statement
}
其中有 StepExecution
,您可以获取需要的变量,这些变量在上下文中用于构建 sql。覆盖 afterPropertiesSet()
以设置 sql
、rowMapper
和 dataSource
。
@Override
public void afterPropertiesSet() throws Exception {
setSql(sql);
setRowMapper(rowMapper);
setDataSource(dataSource);
super.afterPropertiesSet();
}
使用 java 代码而不是 xml 应该始终是 IMO 首选方法,因为您手头有代码,您可以进行调试,这样可以避免潜在的 xml 键入错误。该方法也是可测试的。