Spring batch 将读取的数据标记为";处理「;通过表列标志,然后在末尾还原

Spring batch 将读取的数据标记为";处理「;通过表列标志,然后在末尾还原,spring-batch,Spring Batch,下面是我创建的批处理作业的读卡器、处理器、编写器和步骤的相关部分代码 我需要更新表中读取数据的标志列(源表),以标记此作业正在处理此数据,以便其他应用程序不会拾取该数据。然后,一旦读取记录的处理完成,我需要将该列恢复为原始值,以便其他应用程序也可以处理这些记录 我想,listener是应该采取的方法(ItemReadListener?)。读卡器侦听器似乎只适用于第一步(即更新标志列),而不适用于块末尾的恢复。挑战似乎是使读数据在处理器端可用 有人能提出可能的方法吗 @Bean publi

下面是我创建的批处理作业的读卡器、处理器、编写器和步骤的相关部分代码

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

我想,listener是应该采取的方法(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();
        }
@Bean
公共步骤step1(StepBuilderFactory StepBuilderFactory,
项目读者,项目作者,
项目处理器(处理器){
返回stepBuilderFactory.get(“step1”)
.chunk(常量.SPRING\u批处理\u chunk\u大小)
.读卡器(读卡器)
.处理器(处理器)
.作者(作者)
.taskExecutor(simpleAsyntaskExecutor)
.throttleLimit(常数.throttleLimit)
.build();
}
@豆子
公共项目阅读器(){
JdbcPagingItemReader=新的JdbcPagingItemReader();
reader.setDataSource(数据源);
reader.setRowMapper(new-registancerowMapper());
reader.setQueryProvider(queryProvider);
reader.setPageSize(常量.SPRING\u BATCH\u reader\u PAGE\u SIZE);
返回读取器;
}
@豆子
公共项目处理器(){
返回新的MatchClaimProcessor();
}
@豆子
公共ItemWriter编写器(数据源数据源){
返回新的MatchedClaimWriter();
}

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

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

@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;
}
@Bean
公共步骤step1(StepBuilderFactory StepBuilderFactory,
项目读者,项目作者,
项目处理器(处理器){
返回stepBuilderFactory.get(“step1”)
.chunk(常量.SPRING\u批处理\u chunk\u大小)
.读卡器(同步读卡器)
.处理器(处理器)
.作者(作者)
.taskExecutor(simpleAsyntaskExecutor)
.throttleLimit(常数.throttleLimit)
.build();
}
@豆子
public ItemReader syncReader(){
SynchronizeEditemStreamReader SynchReader=新的SynchronizeEditemStreamReader();
syncReader.setDelegate(reader());
返回同步器;
}
@豆子
公共项目阅读器(){
JdbcPagingItemReader=新的JdbcPagingItemReader();
reader.setDataSource(数据源);
reader.setRowMapper(new-registancerowMapper());
reader.setQueryProvider(queryProvider);
reader.setPageSize(常量.SPRING\u BATCH\u reader\u PAGE\u SIZE);
返回读取器;
}
第二,解决你真正问题的可能方法:

我会使用一个简单的tasklet来“标记”您想要处理的条目。 您可以通过一个简单的UPDATE语句来实现这一点,因为您知道自己的选择标准。这样,您只需要一个调用,因此只需要一个事务

在那之后,我将用读卡器、处理器和写卡器实现一个正常的步骤。 读者必须只阅读标记的条目,这使得select子句也非常简单

为了恢复该标志,您可以在第三步中执行该操作,该步骤作为tasklet实现,并使用适当的UPDATE语句(如第一步)。为了确保在异常情况下恢复标志,只需适当配置作业流,以便即使步骤2失败也执行步骤3(->请参阅我对该问题的回答)

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


在我看来,使用侦听器不是一个好主意,因为事务处理方式不同。

感谢您提供有关reader同步的指导。您的意思是说在返回之前,在
reader()
bean中同步
reader
对象吗?目前,我通过添加两个监听器解决了这个问题——阅读器监听器和处理器监听器。我分别在
afterRead
&restore in和
afterProcess
方法中添加了要更新的逻辑。我在回答中添加了使用SynchronizeEditemStreamReader的代码。所以它只是一个装饰程序?是的。它由SpringBatch提供。你不必自己写。