Spring Batch JdbcPagingItemReader无限循环问题求实现示例
解决JdbcPagingItemReader无限循环问题的正确实现
嘿,我一眼就瞅出你代码里的问题了——循环逻辑完全写错了,这就是导致无限循环的核心原因!咱们一步步来修正:
问题出在哪?
你的这段循环代码:
TransactionDTO primerDto = itemReader.read(); while (primerDto != null) { list.add(itemReader.read()); }
有两个致命问题:
- 第一次读取的
primerDto根本没加到列表里,直接丢了第一条数据; - 循环条件只判断了初始的
primerDto,后续每次调用itemReader.read()返回null时,循环不会终止——因为primerDto还是之前的非null值,导致你会一直调用read(),而JdbcPagingItemReader在没有数据时会持续返回null,自然就无限循环了。
正确的实现示例
下面是修正后的完整代码,我标注了关键的修改点:
public List<TransactionDTO> getTransactions(Integer chunk, LocalDateTime startDate, LocalDateTime endDate) throws Exception { final TransactionMapper transactionMapper = new TransactionMapper(); final SqlPagingQueryProviderFactoryBean sqlPagingQueryProviderFactoryBean = new SqlPagingQueryProviderFactoryBean(); // 配置分页查询提供者 sqlPagingQueryProviderFactoryBean.setDataSource(dataSource); sqlPagingQueryProviderFactoryBean.setSelectClause(env.getProperty("sql.fromdates.select")); sqlPagingQueryProviderFactoryBean.setFromClause(env.getProperty("sql.fromdates.from")); sqlPagingQueryProviderFactoryBean.setWhereClause(env.getProperty("sql.fromdates.where")); sqlPagingQueryProviderFactoryBean.setSortKey(env.getProperty("sql.fromdates.sort")); // 设置查询参数 final Map<String, Object> parametros = new HashMap<>(); parametros.put("startDate", startDate); parametros.put("endDate", endDate); final JdbcPagingItemReader<TransactionDTO> itemReader = new JdbcPagingItemReader<>(); itemReader.setDataSource(dataSource); itemReader.setQueryProvider(sqlPagingQueryProviderFactoryBean.getObject()); // 这里应该用传入的chunk参数作为分页大小,而不是硬编码1 itemReader.setPageSize(chunk); itemReader.setFetchSize(chunk); itemReader.setRowMapper(transactionMapper); // 建议先设置参数,再调用afterPropertiesSet(虽然不是强制,但更符合配置逻辑) itemReader.setParameterValues(parametros); itemReader.afterPropertiesSet(); ExecutionContext executionContext = new ExecutionContext(); itemReader.open(executionContext); List<TransactionDTO> list = new ArrayList<>(); TransactionDTO currentDto; // 核心修正:每次读取后立即判断是否为null,为null则终止循环 while ((currentDto = itemReader.read()) != null) { list.add(currentDto); } itemReader.close(); return list; }
关键注意事项
- 严格遵守ItemReader规范:
read()方法在没有更多数据时必须返回null,你的循环必须以这个返回值作为终止条件,这是Spring Batch ItemReader的核心约定; - 分页大小设置:我把硬编码的
1改成了传入的chunk参数,这样更符合方法的设计意图; - 参数配置顺序:建议先设置
parameterValues再调用afterPropertiesSet(),避免潜在的配置验证问题; - 资源安全关闭:如果担心中间抛出异常导致资源未关闭,可以用try-with-resources语法包裹itemReader:
try (JdbcPagingItemReader<TransactionDTO> itemReader = new JdbcPagingItemReader<>()) { // 配置itemReader... itemReader.open(executionContext); // 读取数据... } catch (Exception e) { // 异常处理逻辑 }
内容的提问来源于stack exchange,提问作者Genaut
相关产品推荐
相关产品推荐

