如何获取 JPA 自定义查询的结果作为页面
How to get results of JPA custom query as Page
我有一个存储库,returns一个Page<Mind>
:
public interface MindRepository extends PagingAndSortingRepository<Mind, Integer> {
Page<Mind> findByCountry(String country, Pageable pageable);
}
以及使用它的控制器:
private MindRepository mindRepository;
@GetMapping(path = "/minds", produces = "application/json")
public Page<Mind> getMinds(String country, Integer page, Integer size) {
Pageable pageable = PageRequest.of(page,size);
return mindRepository.findByCountry(country,pageable);
}
一切正常。 json 中适合 FrontEnd 的控制器 returns Page<Mind>
。
但现在我不得不让查询变得更复杂,有几个过滤器,动态变化。我想像这样使用 createQuery
:
public interface CustomizedMindRepository<T> {
Page<T> findByCountry(String country, Pageable pageable);
}
public interface MindRepository extends PagingAndSortingRepository<Mind, Integer>,CustomizedMindRepository {
Page<Mind> findByCountry(String country, Pageable pageable);
}
public class CustomizedMindRepositoryImpl implements CustomizedMindRepository {
@PersistenceContext
private EntityManager em;
@Override
public Page<Mind> findByCountry(String country, Pageable pageable) {
return em.createQuery("from minds where <dynamical filter> AND <another dynamical filter> AND <...etc>", Mind.class)
.getResultList();
}
}
但是getResultList()
returnsList
,不是Page
:(
最好的解决方法是什么?
如果您想使用 EntityManager.createQuery
,您可以使用 setFirstResult
和 setMaxResults
方法来获得相同的结果。
@Override
public List<Mind> findByCountry(String country, Pageable pageable) {
return em.createQuery("from minds where <dynamical filter> AND <another dynamical filter> AND <...etc>", Mind.class)
.setFirstResult(startPosition)
.setMaxResults(size)
.getResultList();
}
在这种情况下 size
与您的情况具有相同的含义,但 startPosition
不是 page
,而是计算为:
startPosition = page * size
但是,如果您需要构建动态查询 - 考虑使用 Specifications 或 JPA Criteria API.
- 页面存储库调用执行两次调用,一次获取结果,一次获取总大小。因此,您还必须通过执行计数查询来复制该行为
@Override
public Page<Mind> findByCountry(String country, Pageable pageable) {
long offset = pageable.getPageNumber() * pageable.getPageSize();
long limit = pageable.getPageSize();
List<Item> itemsInNextPage = em.createQuery(query)
.setFirstResult(offset)
.setMaxResults(limit)
.getResultList();
long total = // Another query to get the total count
List<Mind> results = em.createQuery("from minds ...", Mind.class)
.getResultList();
return new PageImpl(results, pageable, total);
}
我有一个存储库,returns一个Page<Mind>
:
public interface MindRepository extends PagingAndSortingRepository<Mind, Integer> {
Page<Mind> findByCountry(String country, Pageable pageable);
}
以及使用它的控制器:
private MindRepository mindRepository;
@GetMapping(path = "/minds", produces = "application/json")
public Page<Mind> getMinds(String country, Integer page, Integer size) {
Pageable pageable = PageRequest.of(page,size);
return mindRepository.findByCountry(country,pageable);
}
一切正常。 json 中适合 FrontEnd 的控制器 returns Page<Mind>
。
但现在我不得不让查询变得更复杂,有几个过滤器,动态变化。我想像这样使用 createQuery
:
public interface CustomizedMindRepository<T> {
Page<T> findByCountry(String country, Pageable pageable);
}
public interface MindRepository extends PagingAndSortingRepository<Mind, Integer>,CustomizedMindRepository {
Page<Mind> findByCountry(String country, Pageable pageable);
}
public class CustomizedMindRepositoryImpl implements CustomizedMindRepository {
@PersistenceContext
private EntityManager em;
@Override
public Page<Mind> findByCountry(String country, Pageable pageable) {
return em.createQuery("from minds where <dynamical filter> AND <another dynamical filter> AND <...etc>", Mind.class)
.getResultList();
}
}
但是getResultList()
returnsList
,不是Page
:(
最好的解决方法是什么?
如果您想使用 EntityManager.createQuery
,您可以使用 setFirstResult
和 setMaxResults
方法来获得相同的结果。
@Override
public List<Mind> findByCountry(String country, Pageable pageable) {
return em.createQuery("from minds where <dynamical filter> AND <another dynamical filter> AND <...etc>", Mind.class)
.setFirstResult(startPosition)
.setMaxResults(size)
.getResultList();
}
在这种情况下 size
与您的情况具有相同的含义,但 startPosition
不是 page
,而是计算为:
startPosition = page * size
但是,如果您需要构建动态查询 - 考虑使用 Specifications 或 JPA Criteria API.
- 页面存储库调用执行两次调用,一次获取结果,一次获取总大小。因此,您还必须通过执行计数查询来复制该行为
@Override
public Page<Mind> findByCountry(String country, Pageable pageable) {
long offset = pageable.getPageNumber() * pageable.getPageSize();
long limit = pageable.getPageSize();
List<Item> itemsInNextPage = em.createQuery(query)
.setFirstResult(offset)
.setMaxResults(limit)
.getResultList();
long total = // Another query to get the total count
List<Mind> results = em.createQuery("from minds ...", Mind.class)
.getResultList();
return new PageImpl(results, pageable, total);
}