如何知道 JPA 查询中记录的位置?
我有一个服务,它返回分页结果或多或少地实现了具有此签名的方法:
List<Record> getRecordsPage(long page, int pageSize);
调用它时,我只需创建一个查询并进行如下配置:
TypedQuery<Record> query = entityManager.createQuery(criteriaQuery);
query.setFirstResult(page * pageSize);
query.setMaxResults(pageSize);
这对结果进行了分页。这按预期工作,并且非常简单。
问题
我的另一个要求是实现一种方法来检索包含特定记录的页面。实现具有以下签名的方法:
List<Record> getRecordsPage(Record record, int pageSize);
此方法需要生成记录所在的正确页面。例如,对于getRecordsPage(RECORD4, 2)
调用,考虑数据库状态:
1. RECORD1
2. RECORD2
3. RECORD3
4. RECORD4
5. RECORD5
返回的页面应该是 2,其中包含[RECORD3, RECORD4]
.
该ORDER BY
参数始终设置,并且可以是多个字段。
解决方案到现在
到目前为止,我有一些解决方案是:
- 一点都不好,但它解决了问题:
使用提供的查询,我只选择不分页的 id 并只执行 aindexOf
以找到它的位置,并根据位置我可以找出记录所在的页面,然后使用getRecordsPage(long page, int pageSize)
已经实现的执行常规过程。
- 不太好,因为与数据库高度耦合:
当我使用 MySQL 时,我可以执行类似 : 的 sql select r from (select rownum r, id from t order by x,y) z where z.id = :id
,什么会返回记录的位置,我可以使用它来调用getRecordsPage(long page, int pageSize)
.
好的解决方案
要求:
- 应支持多字段排序;
- 给定一个查询,它将返回记录位置或包含记录的页面偏移量;
一个好的解决方案是:
- 纯粹是JPA;
- 如果在数据库中执行一个额外的查询只是为了找出记录位置,则可以;
- 如果在某些时候使用了休眠就可以了(因为在这种情况下休眠落后于 JPA)。