Spring批处理:JdbcPagingItemReader分页

问题描述 投票:0回答:1

当我做一个简单的批处理时,遇到了一个问题,该批处理从postgresql数据库中读取数据,处理并写入一个csv文件。以下是读者:

 @Bean
@StepScope
public ItemReader<SearchResult> databaseReader(@Qualifier("reportingDataSource") HikariDataSource reportDataSource,
                                           @Value("#{stepExecution}") StepExecution stepExecution) {

    JdbcPagingItemReader<SearchResult> reader = new JdbcPagingItemReader<>();
    reader.setQueryProvider(createQueryProvider());
    reader.setRowMapper(new CustomRowMapper());
    reader.setDataSource(reportDataSource);
    reader.setPageSize(5);
    reader.open(stepExecution.getExecutionContext());
    return reader;
}

private PagingQueryProvider createQueryProvider(SearchTxnRequest searchTxnRequest) {
    SqlitePagingQueryProvider queryProvider = new SqlitePagingQueryProvider();
    queryProvider.setSelectClause("SELECT *");
    queryProvider.setFromClause("from dummy_table");
    queryProvider.setSortKeys(sortBy());
    return queryProvider;
}

private Map<String, Order> sortBy() {
    Map<String, Order> sortConfiguration = new HashMap<>();
    sortConfiguration.put("date", Order.ASCENDING);
    return sortConfiguration;
}

我将虚拟数据插入具有不同ID的'dummy_table'中,但在其他字段(包括日期字段)中使用了相同的数据。正如您在代码中看到的那样,sortBy函数定义了对表中信息进行排序的方式,我只选择了日期字段。问题出现在这里,如果表中的所有行都有相同的日期,则批处理仅返回前5行(如果页面大小为5)。

为什么?好吧,JdbcPagingItemReader使用排序键(在这种情况下仅是日期)进行分页。调试显示以下内容:因此,阅读第一页

2020-03-30 15:01:40 DEBUG [nio-7035-exec-1] o.s.b.i.database.JdbcPagingItemReader    : Reading page 0
2020-03-30 15:01:40 DEBUG [nio-7035-exec-1] o.s.b.i.database.JdbcPagingItemReader    : SQL used for reading first page: [SELECT * FROM from dummy_table ORDER BY date ASC LIMIT 5]

第二页:

2020-03-30 15:01:40 [nio-7035-exec-1] o.s.b.i.database.JdbcPagingItemReader    : Reading page 1
2020-03-30 15:01:40 [nio-7035-exec-1] o.s.b.i.database.JdbcPagingItemReader    : SQL used for reading remaining pages: [SELECT * FROM from dummy_table WHERE ((date > ?)) ORDER BY date ASC LIMIT 5]

您可以看到,分页是由日期排序键完成的。我的问题是表中的所有数据都具有相同的日期。重要的是,明智地选择排序键,以避免出现分页问题。我添加了ID,就可以解决问题。

spring-batch reader
1个回答
0
投票

[您不需要在reader.open方法中调用databaseReader,如果您的阅读器被声明为ItemStreamReader,则Spring Batch将执行此操作。我建议在读取器/写入器bean定义中返回最特定的类型,以便Spring Batch可以正确创建代理。您的情况应该是这样的:

@Bean
@StepScope
public JdbcPagingItemReader<SearchResult> databaseReader(@Qualifier("reportingDataSource") HikariDataSource reportDataSource) {

   JdbcPagingItemReader<SearchResult> reader = new JdbcPagingItemReader<>();
   reader.setQueryProvider(createQueryProvider());
   reader.setRowMapper(new CustomRowMapper());
   reader.setDataSource(reportDataSource);
   reader.setPageSize(5);
   return reader;
}

重要的是,明智地选择排序键,以避免出现分页问题。我添加了ID,就可以解决问题。

是的,正如所记录的,这是JdbcPagingItemReaderAbstractSqlPagingQueryProvider的Javadocs的摘录:

It is important to have a unique key constraint on the sort key

The columns that make up the sort key must be a true key and not just a column to order by

我相信您的日期列不是键,这就是为什么添加ID时起作用的原因。

© www.soinside.com 2019 - 2024. All rights reserved.