如何将JPA自定义查询的结果获取为Page

huangapple go评论133阅读模式
英文:

How to get results of JPA custom query as Page

问题

我有一个仓库,返回一个 Page<Mind>

  1. public interface MindRepository extends PagingAndSortingRepository<Mind, Integer> {
  2. Page<Mind> findByCountry(String country, Pageable pageable);
  3. }

还有一个使用它的控制器:

  1. private MindRepository mindRepository;
  2. @GetMapping(path = "/minds", produces = "application/json")
  3. public Page<Mind> getMinds(String country, Integer page, Integer size) {
  4. Pageable pageable = PageRequest.of(page, size);
  5. return mindRepository.findByCountry(country, pageable);
  6. }

一切都正常。控制器以适合前端的 JSON 格式返回 Page<Mind>

但现在我必须使查询更复杂,带有多个动态更改的筛选器。我想像这样使用 createQuery

  1. public interface CustomizedMindRepository<T> {
  2. Page<T> findByCountry(String country, Pageable pageable);
  3. }
  4. public interface MindRepository extends PagingAndSortingRepository<Mind, Integer>, CustomizedMindRepository {
  5. Page<Mind> findByCountry(String country, Pageable pageable);
  6. }
  7. public class CustomizedMindRepositoryImpl implements CustomizedMindRepository {
  8. @PersistenceContext
  9. private EntityManager em;
  10. @Override
  11. public Page<Mind> findByCountry(String country, Pageable pageable) {
  12. return em.createQuery("from minds where <动态筛选条件> AND <另一个动态筛选条件> AND <...等等>", Mind.class)
  13. .getResultList();
  14. }
  15. }

getResultList() 返回的是 List,而不是 Page 如何将JPA自定义查询的结果获取为Page

解决这个问题的最佳方法是什么呢?

英文:

I have a repository, that returns a Page&lt;Mind&gt;:

  1. public interface MindRepository extends PagingAndSortingRepository&lt;Mind, Integer&gt; {
  2. Page&lt;Mind&gt; findByCountry(String country, Pageable pageable);
  3. }

And a controller that use it:

  1. private MindRepository mindRepository;
  2. @GetMapping(path = &quot;/minds&quot;, produces = &quot;application/json&quot;)
  3. public Page&lt;Mind&gt; getMinds(String country, Integer page, Integer size) {
  4. Pageable pageable = PageRequest.of(page,size);
  5. return mindRepository.findByCountry(country,pageable);
  6. }

And everything is ok. Controller returns Page&lt;Mind&gt; in json that suits FrontEnd.

But now I have to make the query more complicated, with several filters, changing dynamically. I would like to use createQuery like this:

  1. public interface CustomizedMindRepository&lt;T&gt; {
  2. Page&lt;T&gt; findByCountry(String country, Pageable pageable);
  3. }
  4. public interface MindRepository extends PagingAndSortingRepository&lt;Mind, Integer&gt;,CustomizedMindRepository {
  5. Page&lt;Mind&gt; findByCountry(String country, Pageable pageable);
  6. }
  7. public class CustomizedMindRepositoryImpl implements CustomizedMindRepository {
  8. @PersistenceContext
  9. private EntityManager em;
  10. @Override
  11. public Page&lt;Mind&gt; findByCountry(String country, Pageable pageable) {
  12. return em.createQuery(&quot;from minds where &lt;dynamical filter&gt; AND &lt;another dynamical filter&gt; AND &lt;...etc&gt;&quot;, Mind.class)
  13. .getResultList();
  14. }
  15. }

But getResultList() returns List, not Page 如何将JPA自定义查询的结果获取为Page

What is the best way to solve it?

答案1

得分: 1

  1. @Override
  2. public Page<Mind> findByCountry(String country, Pageable pageable) {
  3. long offset = pageable.getPageNumber() * pageable.getPageSize();
  4. long limit = pageable.getPageSize();
  5. List<Item> itemsInNextPage = em.createQuery(query)
  6. .setFirstResult(offset)
  7. .setMaxResults(limit)
  8. .getResultList();
  9. long total = // 另一个查询以获取总数
  10. List<Mind> results = em.createQuery("from minds ...", Mind.class)
  11. .getResultList();
  12. return new PageImpl(results, pageable, total);
  13. }
英文:
  • Page repository call executes two calls, one to get the results and another to get the total size. So you have to replicate that behaviour by doing a count query as well
  1. @Override
  2. public Page&lt;Mind&gt; findByCountry(String country, Pageable pageable) {
  3. long offset = pageable.getPageNumber() * pageable.getPageSize();
  4. long limit = pageable.getPageSize();
  5. List&lt;Item&gt; itemsInNextPage = em.createQuery(query)
  6. .setFirstResult(offset)
  7. .setMaxResults(limit)
  8. .getResultList();
  9. long total = // Another query to get the total count
  10. List&lt;Mind&gt; results = em.createQuery(&quot;from minds ...&quot;, Mind.class)
  11. .getResultList();
  12. return new PageImpl(results, pageable, total);
  13. }

答案2

得分: 0

如果您想使用EntityManager.createQuery,您可以使用setFirstResultsetMaxResults方法来实现相同的结果。

  1. @Override
  2. public List<Mind> findByCountry(String country, Pageable pageable) {
  3. return em.createQuery("from minds where <动态筛选条件> AND <另一个动态筛选条件> AND <...等等>", Mind.class)
  4. .setFirstResult(startPosition)
  5. .setMaxResults(size)
  6. .getResultList();
  7. }

在这种情况下,size 的含义与您的情况相同,但是startPosition 不是一个“页”,而是通过以下方式计算:

  1. startPosition = page * size

但是,如果您需要构建动态查询,请考虑使用Specifications或者JPA Criteria API。

英文:

If you want to use EntityManager.createQuery, you are given setFirstResult and setMaxResults methods to achieve the same results.

  1. @Override
  2. public List&lt;Mind&gt; findByCountry(String country, Pageable pageable) {
  3. return em.createQuery(&quot;from minds where &lt;dynamical filter&gt; AND &lt;another dynamical filter&gt; AND &lt;...etc&gt;&quot;, Mind.class)
  4. .setFirstResult(startPosition)
  5. .setMaxResults(size)
  6. .getResultList();
  7. }

In this case size have the same meaning as in your case, but startPosition is not a page, but is calculated as:

  1. startPosition = page * size

But, if you need to build dymanic query - consider using Specifications or JPA Criteria API.

huangapple
  • 本文由 发表于 2020年7月24日 16:25:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/63069770.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定