[英]Implementing pagination in JPA EntityManager createNativeQuery
I am writing a query using JPA EntityManager createNativeQuery
and I want to apply pagination.我正在使用
JPA EntityManager createNativeQuery
编写查询,我想应用分页。 Following is the code I have implemented so far:以下是我到目前为止实现的代码:
private static final int NO_OF_RESULTS_IN_A_PAGE = 30;
public Page<Car> getFilteredCars(int page, String model, String manufacturedYear) {
Pageable pageable = PageRequest.of(page, NO_OF_RESULTS_IN_A_PAGE, Sort.by("addedDate").descending());
StringBuilder sb = new StringBuilder("SELECT c.* FROM car c WHERE c.model = ").append(model).append(" AND");
if(manufacturedYear != null) {
sb.append(" c.manufactured_year = ").append(manufacturedYear).append(" AND");
}
sb.append(" c.for_sale = true ORDER BY c.added_date DESC");
Query query = entityManager.createNativeQuery(sb.toString(), Car.class);
query.setFirstResult(page * NO_OF_RESULTS_IN_A_PAGE);
query.setMaxResults((page * NO_OF_RESULTS_IN_A_PAGE) + NO_OF_RESULTS_IN_A_PAGE);
Page<Car> results = new PageImpl<>(query.getResultList(), pageable, 0);
return results;
}
The problem is that in the new PageImpl<>
constructor, I have to pass the total number of items as the third argument.问题是在
new PageImpl<>
构造函数中,我必须将项目总数作为第三个参数传递。 And before the query runs, I don't know how many items are there.在查询运行之前,我不知道有多少项目。 If I pass 0 (as in the code above), I will only get back the first page and the total items will be 30 even when there are actually over 1000 items in the database.
如果我传递 0(如上面的代码),我只会返回第一页,即使数据库中实际上有超过 1000 个项目,总项目也将是 30。 There is also a simpler constructor for
PageImpl
taking only one argument (the query.getResultList()
), but then the result would be unpaginated. PageImpl
还有一个更简单的构造函数,它只接受一个参数( query.getResultList()
),但结果将是未分页的。 This has caused me to run the query twice, once to get the total number of items returned from the query (unpaginated) and then using it to get the paginated results.这导致我运行了两次查询,一次是获取从查询返回的项目总数(未分页),然后使用它来获取分页结果。 Clearly there must be a better way to achieve this, which I have not been able to figure out.
显然,必须有更好的方法来实现这一点,而我一直无法弄清楚。
Please note that my actual query is much more complex that the one depicted above involving multiple if-else conditional checks and hence not suitable to query via simple JpaRepository
implementation or by using @Query
with which pagination could have been easily achieved.请注意,我的实际查询比上面描述的涉及多个 if-else 条件检查的查询要复杂得多,因此不适合通过简单的
JpaRepository
实现或使用可以轻松实现分页的@Query
进行查询。
I fear there is no other way than to let the DB count the total number of cars through an additional query before you perform the actual select.我担心在执行实际的 select 之前,除了让数据库通过附加查询计算汽车总数之外别无他法。 Like
喜欢
SELECT count(1) FROM car c WHERE c.model = ...
Simple counts are much faster than selects that returns n>1 rows.简单计数比返回 n>1 行的选择要快得多。 Of course the counting will slow down the execution but on modern DB this will cost a few milliseconds only - something we humans will not recognize;-)
当然,计数会减慢执行速度,但在现代数据库上,这只会花费几毫秒——我们人类无法识别的东西;-)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.