2

(Note: all code examples are extremely simple. I know there are other ways to do such simple queries. The problem I am demonstrating, however, is a bigger deal for more complex queries).

There is a known issue with Spring JPA Repositories and paginated queries that I'm really hoping there is a good solution for. In JPQL, it is possible to use JOIN FETCH to specify that I want to eagerly fetch a related entity, rather than doing it lazily. This avoids the N+1 problem, among other things. JOIN FETCH requires that the owner of the association is included in the select clause. Here is a very simple example of the type of query I'm talking about:

@Query("""
    SELECT p
    FROM Person p
    JOIN FETCH p.address
""")
Page<Person> getPeopleAndAddresses(Pageable page);

The problem with this kind of query is the pagination piece. When returning a Page, Spring will do the query I wrote but then also do a count query to get the total possible records. Spring appears to take my query exactly as written, and just replace SELECT p with SELECT COUNT(p). Doing this means that the owner of the JOIN FETCH association is no longer present in the SELECT clause, which then results in the JPQL giving an error.

The only way I know how to resolve this is to construct the query with separate query and countQuery values, like this:

@Query(query = """
    SELECT p
    FROM Person p
    JOIN FETCH p.address
""", countQuery = """
    SELECT COUNT(p)
    FROM Person p
    """)
Page<Person> getPeopleAndAddresses(Pageable page);

This resolves the JPQL JOIN FETCH error, because the count query no longer contains a JOIN FETCH clause. However, for complex queries with sophisticated JOINs and WHERE clauses, this will lead to excessive code duplication as I will have to write all that logic in two places.

This seems like the kind of issue where there really should be a better solution available. I'm exploring various alternatives, including Specifications (mixed feelings), Blaze Persistence, and others. However, I'm wondering if there is some way in Spring itself to resolve this issue so that the first code example would work without an error?

halfer
  • 19,824
  • 17
  • 99
  • 186
craigmiller160
  • 5,751
  • 9
  • 41
  • 75
  • Could you please check the solution of https://stackoverflow.com/questions/21549480/spring-data-fetch-join-with-paging-is-not-working ? Basically just remove `FETCH` into countQuery, `SELECT p FROM Person p JOIN p.address` – minh tri Vo Sep 17 '22 at 16:54
  • Have you found a solution to this problem? I ran into the same issue using Micronaut Data with JPA specifications. – sorin.silaghi Mar 03 '23 at 14:04
  • I also would like to know the solution. I have the same problem. – Ventrue Jun 29 '23 at 17:49

0 Answers0