带有 sortKeys 和参数值的 Spring Batch Paging

2024-01-07

我有一个在 Spring Boot 中运行的 Spring Batch 项目,该项目工作得很好。对于我的读者,我将 JdbcPagingItemReader 与 MySql PagingQueryProvider 结合使用。

@Bean
public ItemReader<Person> reader(DataSource dataSource) {
    MySqlPagingQueryProvider provider = new MySqlPagingQueryProvider()
    provider.setSelectClause(ScoringConstants.SCORING_SELECT_STATEMENT)
    provider.setFromClause(ScoringConstants.SCORING_FROM_CLAUSE)
    provider.setSortKeys("p.id": Order.ASCENDING)

    JdbcPagingItemReader<Person> reader = new JdbcPagingItemReader<Person>()
    reader.setRowMapper(new PersonRowMapper())
    reader.setDataSource(dataSource)
    reader.setQueryProvider(provider)
    //Setting these caused the exception
    reader.setParameterValues(
        startDate: new Date() - 31,
        endDate: new Date()
    ) 
    reader.afterPropertiesSet()
    return reader
}

但是,当我使用一些命名参数修改查询以替换以前硬编码的日期值并在读取器上设置这些参数值(如上所示)时,我收到以下异常second页面读取(第一页工作正常,因为分页查询提供程序尚未使用 _id 参数):

org.springframework.dao.InvalidDataAccessApiUsageException: No value supplied for the SQL parameter '_id': No value registered for key '_id'
at org.springframework.jdbc.core.namedparam.NamedParameterUtils.buildValueArray(NamedParameterUtils.java:336)
at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.getPreparedStatementCreator(NamedParameterJdbcTemplate.java:374)
at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.query(NamedParameterJdbcTemplate.java:192)
at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.query(NamedParameterJdbcTemplate.java:199)
at org.springframework.batch.item.database.JdbcPagingItemReader.doReadPage(JdbcPagingItemReader.java:218)
at org.springframework.batch.item.database.AbstractPagingItemReader.doRead(AbstractPagingItemReader.java:108)

下面是一个 SQL 示例,默认情况下没有 WHERE 子句。当阅读第二页时,会自动创建一个:

select *, (select id from family f where date_created between :startDate and :endDate and f.creator_id = p.id)  from person p

在第二页上,sql 被修改为以下内容,但是似乎没有提供 _id 的命名参数:

select *, (select id from family f where date_created between :startDate and :endDate and f.creator_id = p.id) from person p WHERE id > :_id

我想知道是否无法将 MySqlPagingQueryProvider 排序键与 JdbcPagingItemReader 中设置的其他命名参数一起使用。如果不是,解决这个问题的最佳替代方案是什么?我需要能够为查询提供参数并对其进行分页(相对于使用游标)。谢谢你!


我通过一些激烈的调试解决了这个问题。原来MySqlPagingQueryProvider利用了一个方法getSortKeysWithoutAliases()当它构建针对第一页和后续页面运行的 SQL 查询时。因此它附加and (p.id > :_id)代替and (p.id > :_p.id)。稍后,当创建第二个页面排序值并将其存储在 JdbcPagingItemReader 中时startAfterValues它将使用原始字段"p.id"指定的字符串并最终放入命名参数映射对中("_p.id",10)。但是,当读取器尝试在查询中填写 _id 时,它不存在,因为读取器使用了非别名删除键。

长话短说,在定义排序键时,我必须删除别名引用。

provider.setSortKeys("p.id": Order.ASCENDING)

为了让一切都能很好地协同工作,必须更改为

provider.setSortKeys("id": Order.ASCENDING)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

带有 sortKeys 和参数值的 Spring Batch Paging 的相关文章

随机推荐