Spring 数据 JDBC 使用分页创建查询抱怨 IncorrectResultSizeDataAccessException:结果大小不正确

Spring data JDBC query creation with pagination complains IncorrectResultSizeDataAccessException: Incorrect result size

我正在努力尝试分页功能,如 reference document 中所述。
这是我的 table 架构:

CREATE TABLE cities
(
    id      int PRIMARY KEY,
    name    varchar(255),
    pref_id int
);

存储库:

public interface CityRepository extends CrudRepository<CityEntity, Integer> {

  Page<CityEntity> findAll(Pageable pageable);

  // get all cities in the prefecture
  Page<CityEntity> findByPrefId(Integer prefId, Pageable pageable);
}

测试代码:

Page<CityEntity> allCities = repository.findAll(PageRequest.of(0, 10));
Page<CityEntity> cities = repository.findByPrefId(1, PageRequest.of(0, 10));

findAll 运行良好,但 findByPrefId 抛出以下错误:

Incorrect result size: expected 1, actual 10
org.springframework.dao.IncorrectResultSizeDataAccessException: Incorrect result size: expected 1, actual 10
    at org.springframework.dao.support.DataAccessUtils.nullableSingleResult(DataAccessUtils.java:100)
    at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.queryForObject(NamedParameterJdbcTemplate.java:237)
    at org.springframework.data.jdbc.repository.query.AbstractJdbcQuery.lambda$singleObjectQuery(AbstractJdbcQuery.java:115)
    at org.springframework.data.jdbc.repository.query.PartTreeJdbcQuery.execute(PartTreeJdbcQuery.java:98)
    at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor$QueryMethodInvoker.invoke(QueryExecutorMethodInterceptor.java:195)
    at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:152)
    at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:130)
...

如果我将方法签名更改为 List<CityEntity> findByPrefId(Integer prefId, Pageable pageable),它会起作用。

我错过了什么吗?我使用的是最新版本的 spring-data-jdbc (2.0.2.RELEASE).

我不知道技术细节,但这是我从经验中学到的。

在您的情况下,如果城市总数少于 pageable.getPageSize(),那么您的存储库将 return 一个列表<>。

但如果城市总数大于 pageable.getPageSize(),那么您的存储库将 return 一个页面<>。

知道这一点后,我就是这样做的。

    Long amount = repository.countByPrefId(prefId);
    if(pagination.getPageSize()>amount ) {
       List<CityEntity> list = repository.findByPrefId(prefId);
    } else {
       Page<CityEntity> pages = repository.findByPrefId(person, PageRequest.of(0, 10));
    }

这也意味着在您的存储库中您将有两种不同的方法,一种使用 Pageable 作为参数,另一种使用 only PrefId 作为参数。

我相信接受的答案是指 Spring Data JPA,它通过基于从自定义查询派生的计数查询返回页面或通过 countQuery 手动设置来工作,没有理由if/else.

然而,这种扁平化在 Spring 数据 JDBC 中不起作用。

https://jira.spring.io/browse/DATAJDBC-554

link 中提供的解决方法,但仅供参考:

    interface FooRepository extends PagingAndSortingRepository<FooEntity, Long> {
        List<FooEntity> findAllByBar(String bar, Pageable pageable);
        Long countAllByBar(String bar);
    }

然后像这样组合这 2 个查询:

    List<FooEntity> fooList = repository.findAllByBar("...", pageable);
    Long fooTotalCount = repository.countAllByBar("...");

    Page<FooEntity> fooPage = PageableExecutionUtils.getPage(fooList, pageable, () -> fooTotalCount);