You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义JdbcPagingItemReader二次迭代参数未设置异常求助

问题:Spring Batch JdbcPagingItemReader第二次迭代时参数未设置异常

我创建了一个继承JdbcPagingItemReader的类,内部配置如下:

@PostConstruct
public void init() throws Exception {
    setDataSource(dsSrv.getUserDataSource());
    setPageSize(Integer.parseInt(pageSize));
    setFetchSize(Integer.parseInt(pageSize));
    setQueryProvider(queryProvider2(dsSrv.getUserDataSource()));
    setRowMapper(rowMapper());
}
private PagingQueryProvider queryProvider2(DataSource ds) throws Exception {
    SqlPagingQueryProviderFactoryBean queryProvider=new SqlPagingQueryProviderFactoryBean();
    final Map<String, Order> sortKeys = new HashMap<>();
    sortKeys.put("ID", Order.ASCENDING);

    queryProvider.setDataSource(ds);
    queryProvider.setSelectClause("*");
    queryProvider.setFromClause("D_TABLE");
    queryProvider.setWhereClause("ID = '5d7031e6-10f2-4247-b581-17b2fe96449a'");
    queryProvider.setSortKeys(sortKeys);
    return queryProvider.getObject();
}

首次迭代时查询语句符合预期:SELECT TOP 10 * FROM D_TABLE WHERE (ID= '5d7031e6-10f2-4247-b581-17b2fe96449a'),但第二次迭代时生成的查询语句自动添加了AND ((ID > ?))条件,却未设置该参数,抛出如下异常:

org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [SELECT TOP 10 * FROM D_TABLE WHERE (ID = '5d7031e6-10f2-4247-b581-17b2fe96449a') AND ((ID > ?)) ORDER BY ID ASC]; SQL state [null]; error code [0]; The value is not set for the parameter number 1.; nested exception is com.microsoft.sqlserver.jdbc.SQLServerException: The value is not set for the parameter number 1.

解决方案

原因分析

JdbcPagingItemReader的分页逻辑依赖sortKeys定义的字段作为分页游标:每次查询会记录当前页最后一条数据的游标字段值,下一页查询时会自动添加游标字段 > 上一页最后值的条件实现分页。但你的where条件已经固定了唯一ID,第一次查询后无后续数据,分页游标逻辑触发时无法正确绑定参数,从而抛出异常。

解决方法

  1. 一次性查询所有数据
    由于查询条件仅匹配单条数据,直接将pageSize设置为足够大的值(比如Integer.MAX_VALUE),让JdbcPagingItemReader一次性获取全部结果,避免触发分页迭代:

    setPageSize(Integer.MAX_VALUE);
    setFetchSize(Integer.MAX_VALUE);
    
  2. 改用JdbcCursorItemReader
    如果场景不需要分页,直接使用JdbcCursorItemReader替代JdbcPagingItemReader,它适合一次性读取结果集,无分页游标逻辑:

    // 示例JdbcCursorItemReader配置
    JdbcCursorItemReader<YourEntity> reader = new JdbcCursorItemReader<>();
    reader.setDataSource(dsSrv.getUserDataSource());
    reader.setSql("SELECT * FROM D_TABLE WHERE ID = '5d7031e6-10f2-4247-b581-17b2fe96449a'");
    reader.setRowMapper(rowMapper());
    
  3. 调整分页逻辑(不推荐此场景)
    若必须保留分页,需确保sortKeys字段未被where条件固定死,同时使用参数化查询绑定条件,让分页游标参数能正确传递。但此场景下分页无实际意义,不建议使用。

内容的提问来源于stack exchange,提问作者thefiery77

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 02:16:01