Resolving Pagination Issues with @Query and Pageable in Spring Data JPA

Nov 26, 2025 · Programming · 8 views · 7.8

Keywords: Spring Data JPA | @Query Annotation | Pagination Query | Native SQL | Pageable Parameter

Abstract: This article provides an in-depth analysis of pagination issues when combining @Query annotation with Pageable parameters in Spring Data JPA. By examining Q&A data and reference documentation, it explains why countQuery parameter is mandatory for native SQL queries to achieve proper pagination. The article also discusses the importance of table aliases in pagination queries and offers complete code examples and solutions to help developers avoid common pagination implementation errors.

Problem Background and Phenomenon Analysis

In Spring Data JPA development practice, developers often encounter scenarios where custom queries need to be combined with pagination functionality. From the provided Q&A data, a typical issue emerges: when using the @Query annotation to define native SQL queries, the query executes normally if the method signature doesn't include a Pageable parameter; however, once a Pageable parameter is added, Spring switches to parsing the method name, resulting in a No property full found exception.

The specific code comparison clearly demonstrates this phenomenon:

// Without Pageable parameter - works correctly
@Query(value = "select * from internal_uddi where urn like %?1% or contact like %?1%", 
       nativeQuery = true)
List<UrnMapping> fullTextSearch(String text);

// With Pageable parameter - throws exception
@Query(value = "select * from internal_uddi where urn like %?1% or contact like %?1%",
       nativeQuery = true)
Page<UrnMapping> fullTextSearch(String text, Pageable pageable);

Root Cause Analysis

The fundamental cause of this issue lies in Spring Data JPA's handling mechanism for pagination queries. When a method includes a Pageable parameter, Spring expects to automatically generate pagination queries, but for native SQL queries, Spring cannot automatically derive the corresponding count query.

According to the Spring official forum discussion referenced in Answer 2, to implement pagination with native SQL queries, the count query must be explicitly provided. This is because pagination functionality requires knowing the total number of records to calculate the total number of pages, and Spring cannot automatically extract this information from native SQL.

Solution Implementation

The correct implementation approach is to specify both value and countQuery parameters in the @Query annotation:

public interface UrnMappingRepository extends JpaRepository<UrnMapping, Long> {
    @Query(value = "SELECT * FROM internal_uddi WHERE urn LIKE %?1% OR contact LIKE %?1%",
           countQuery = "SELECT COUNT(*) FROM internal_uddi WHERE urn LIKE %?1% OR contact LIKE %?1%",
           nativeQuery = true)
    Page<UrnMapping> fullTextSearch(String text, Pageable pageable);
}

Importance of Table Aliases

Answer 2 also emphasizes the importance of using table aliases in pagination queries. When queries involve subqueries or complex joins, using table aliases can prevent potential naming conflicts and parsing errors:

// Recommended approach with table aliases
@Query(value = "SELECT * FROM internal_uddi iu WHERE iu.urn LIKE %?1% OR iu.contact LIKE %?1%",
       countQuery = "SELECT COUNT(*) FROM internal_uddi iu WHERE iu.urn LIKE %?1% OR iu.contact LIKE %?1%",
       nativeQuery = true)
Page<UrnMapping> fullTextSearch(String text, Pageable pageable);

Usage of Pagination Parameters

Drawing from the Baeldung article content, we can understand how to correctly create and use Pageable parameters:

// Create pagination requests
Pageable firstPage = PageRequest.of(0, 10); // Page 1, 10 records per page
Pageable secondPage = PageRequest.of(1, 20); // Page 2, 20 records per page

// Use pagination query
Page<UrnMapping> result = urnMappingRepository.fullTextSearch("searchText", firstPage);

// Retrieve pagination information
List<UrnMapping> content = result.getContent(); // Current page data
int totalPages = result.getTotalPages(); // Total number of pages
long totalElements = result.getTotalElements(); // Total number of records

Integration of Sorting Functionality

Combining the sorting functionality from the reference article, we can integrate sorting into pagination queries:

// Create pagination request with sorting
Pageable sortedPageable = PageRequest.of(0, 10, Sort.by("urn").ascending());

// Or more complex sorting
Pageable complexSort = PageRequest.of(0, 10, 
    Sort.by("contact").descending().and(Sort.by("urn").ascending()));

Performance Considerations

When using pagination queries, performance optimization should be considered:

Best Practices Summary

Based on the above analysis, we summarize the following best practices:

  1. When using native SQL pagination queries, the countQuery must be explicitly provided
  2. Use meaningful table aliases to avoid potential naming conflicts
  3. Design count queries reasonably to ensure performance
  4. Select appropriate return types based on business requirements
  5. In complex query scenarios, consider using JPQL instead of native SQL for better framework support

By following these practices, developers can fully leverage Spring Data JPA's pagination functionality while avoiding common implementation pitfalls.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.