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);
我正在努力尝试分页功能,如 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);