将数据从 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() 以设置 sqlrowMapperdataSource

@Override
public void afterPropertiesSet() throws Exception {
    setSql(sql);
    setRowMapper(rowMapper);
    setDataSource(dataSource);
    super.afterPropertiesSet();
}

使用 java 代码而不是 xml 应该始终是 IMO 首选方法,因为您手头有代码,您可以进行调试,这样可以避免潜在的 xml 键入错误。该方法也是可测试的。