Spring Batch JdbcCursorItemReader重复读取首100条数据问题
解决Spring Batch JdbcCursorItemReader重复读取前100条数据的问题
问题原因
你在SQL中硬编码了fetch next 100 rows only,导致每次JdbcCursorItemReader执行查询时都会返回固定的前100条数据,完全绕过了Spring Batch基于游标滚动的批量读取机制。chunk(100)是指每次从游标中读取100条数据交给处理器/写入器,并非让SQL仅返回100条结果。
解决方案一:使用JdbcCursorItemReader原生游标机制
直接移除SQL中的行数限制,让JdbcCursorItemReader通过游标自动滚动读取后续数据:
@Bean public JdbcCursorItemReader<Object> itemReader() { JdbcCursorItemReader<Object> reader = new JdbcCursorItemReader<>(); reader.setDataSource(dataSource); reader.setSql("select * from <table>"); // 移除fetch next限制 reader.setRowMapper(new ObjectRowMapper()); // 可选:设置fetchSize优化数据库交互性能(与chunk size对应即可) reader.setFetchSize(100); return reader; }
解决方案二:改用JdbcPagingItemReader(分页式读取)
如果你的数据库对游标支持有限,或更倾向于分页读取,可以使用JdbcPagingItemReader,它会自动生成分页SQL,确保每次读取下一批数据:
@Bean public JdbcPagingItemReader<Object> itemReader() throws Exception { SqlPagingQueryProviderFactoryBean queryProvider = new SqlPagingQueryProviderFactoryBean(); queryProvider.setDataSource(dataSource); queryProvider.setSelectClause("select *"); queryProvider.setFromClause("from <table>"); // 必须指定唯一排序字段,保证分页数据不重复、不遗漏 queryProvider.setSortKey("id"); // 替换为你的表主键或唯一索引字段 JdbcPagingItemReader<Object> reader = new JdbcPagingItemReader<>(); reader.setDataSource(dataSource); reader.setQueryProvider(queryProvider.getObject()); reader.setRowMapper(new ObjectRowMapper()); reader.setPageSize(100); // 与chunk size保持一致 return reader; }
关键说明
JdbcCursorItemReader依赖数据库游标,适合大数据量读取,性能更优;JdbcPagingItemReader通过分页SQL实现,无需依赖游标,但必须指定排序字段;- 不要混淆
chunk size和SQL中的行数限制,前者是Spring Batch的批量处理粒度,后者是SQL返回的结果集大小。
内容的提问来源于stack exchange,提问作者Ajit Singh
相关产品推荐
相关产品推荐

