spring-batch - Spring Batch:JdbcPagingItemReader 分页
问题描述
当我做一个从 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;
}
我将虚拟数据插入到“dummy_table”中,ID 不同,但其他字段中的数据相同,包括日期字段。正如您在代码中看到的,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,这解决了问题。
解决方案
您不需要调用reader.open
您的databaseReader
方法,如果您的阅读器被声明为ItemStreamReader
. 我建议在读取器/写入器 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,这解决了问题。
是的,如文档所述,这里是JdbcPagingItemReader和AbstractSqlPagingQueryProvider的 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 时它可以工作。
推荐阅读
- c# - 如何在检查特定属性的可枚举列表中搜索重复项
- sql - 返回 postgresql 中的行数
- python-3.x - 在第一列是周末日期的数据框中删除行
- python - 当只有输入发生变化时,多次使用同一个 TensorFlow Session 有什么缺点吗?
- eclipse - 如何将功能分支的更改合并到 Eclipse 中的主分支?
- python - Python“请参阅帮助(类型(自我))以获取准确的签名。”
- vba - VBA中添加行的最大长度
- javascript - 错误:保留字 'var' javascript/vue
- python - 这个循环不像我想要的那样循环。我希望它循环直到有有效的输入
- python - for循环没有在python中执行