标记读取数据为"处理"通过表列标志然后在结束时恢复

时间:2016-08-29 05:42:19

标签: spring-batch

以下是我创建的批处理作业的阅读器,处理器,编写器和步骤的相关代码部分。

我需要更新表格中的标志列,从中读取数据(源表)以标记此作业正在处理此数据,以便其他应用程序不会拿起那些数据。然后,一旦读取记录的处理完成,我需要将该列恢复为原始值,以便其他应用程序也可以处理这些记录。

我想,听众是采取的方法(ItemReadListener?)。读者监听器似乎只适用于第一步(即更新标志列),但不适用于块结束时的恢复。挑战似乎是在处理器末端提供读取数据。

有人可以建议可行的方法吗?

@Bean
    public Step step1(StepBuilderFactory stepBuilderFactory,
            ItemReader<RemittanceVO> reader, ItemWriter<RemittanceClaimVO> writer,
            ItemProcessor<RemittanceVO, RemittanceClaimVO> processor) {

        return stepBuilderFactory.get("step1")
                .<RemittanceVO, RemittanceClaimVO> chunk(Constants.SPRING_BATCH_CHUNK_SIZE)
                .reader(reader)
                .processor(processor)
                .writer(writer)
                .taskExecutor(simpleAsyntaskExecutor)
                .throttleLimit(Constants.THROTTLE_LIMIT)
                .build();
    }

@Bean
    public ItemReader<RemittanceVO> reader() {
        JdbcPagingItemReader<RemittanceVO> reader = new JdbcPagingItemReader<RemittanceVO>();
        reader.setDataSource(dataSource);
        reader.setRowMapper(new RemittanceRowMapper());
        reader.setQueryProvider(queryProvider);
        reader.setPageSize(Constants.SPRING_BATCH_READER_PAGE_SIZE);
        return reader;
    }



@Bean
 public ItemProcessor<RemittanceVO, RemittanceClaimVO> processor() {
            return new MatchClaimProcessor();
        }

@Bean
        public ItemWriter<RemittanceClaimVO> writer(DataSource dataSource) {
            return new MatchedClaimWriter();
        }

我几天前开始使用Spring Batch,所以不熟悉所有提供的建模和模式。

1 个答案:

答案 0 :(得分:1)

首先,关于使用asyncTaskExecutor的一个小提示:你必须同步阅读器,否则你会遇到并发问题。您可以使用SynchronizedItemStreamReader执行此操作:

@Bean
public Step step1(StepBuilderFactory stepBuilderFactory,
        ItemReader<RemittanceVO> reader, ItemWriter<RemittanceClaimVO> writer,
        ItemProcessor<RemittanceVO, RemittanceClaimVO> processor) {

    return stepBuilderFactory.get("step1")
            .<RemittanceVO, RemittanceClaimVO> chunk(Constants.SPRING_BATCH_CHUNK_SIZE)
            .reader(syncReader)
            .processor(processor)
            .writer(writer)
            .taskExecutor(simpleAsyntaskExecutor)
            .throttleLimit(Constants.THROTTLE_LIMIT)
            .build();
}


@Bean
public ItemReader<RemittanceVO> syncReader() {
    SynchronizedItemStreamReader<RemittanceVO> syncReader = new SynchronizedItemStreamReader<>();

    syncReader.setDelegate(reader());

    return syncReader;
}


@Bean
public ItemReader<RemittanceVO> reader() {
    JdbcPagingItemReader<RemittanceVO> reader = new JdbcPagingItemReader<RemittanceVO>();
    reader.setDataSource(dataSource);
    reader.setRowMapper(new RemittanceRowMapper());
    reader.setQueryProvider(queryProvider);
    reader.setPageSize(Constants.SPRING_BATCH_READER_PAGE_SIZE);
    return reader;
}

其次,一个可能的方法来解决你真正的问题:

我会使用一个简单的tasklet来标记&#34;您要处理的条目。 您可以使用一个简单的UPDATE语句来完成此操作,因为您知道您的选择标准。这样,您只需要一次调用,因此只需要一次交易。

之后,我会用读者,处理器和编写器实现正常步骤。 读者必须只读取标记的条目,使您的select子句也非常简单。

为了恢复该标志,您可以在第三步中执行该操作,该步骤作为tasklet实现并使用适当的UPDATE语句(如第一步)。要确保在异常的情况下恢复该标志,只需适当配置您的作业流程,以便即使第2步失败也执行第3步( - &gt;查看我对此问题的回答Spring Batch Java Config: Skip step when exception and go to next steps

当然,如果使用compositeItemWriter,也可以在编写块时恢复标志。但是,如果在步骤2中发生异常,则需要一种策略如何恢复标志。

IMO,使用监听器并不是一个好主意,因为事务处理方式不同。