简体   繁体   中英

Spring Data pagination

Just face strange behavior of Spring Data JPA 2.2.0.

Product and Category are two very simple entities with one-to-many relations. Notice that in my case some products could have no category.

I make this query

@Query("select p, c" +
        "from Product p " +
        "left join fetch Category c on p.category.id = c.id " +
        "where (:categoryId = -1L or c.id = :categoryId) and " +
        "(:priceFrom is null or p.price >= :priceFrom) and " +
        "(:priceTo is null or p.price <= :priceTo)")
Page<Product> filterProducts(@Param("categoryId") Long categoryId,
                             @Param("priceFrom") BigDecimal priceFrom,
                             @Param("priceTo") BigDecimal priceTo,
                             Pageable pageable);

But method call returns Page<Object[]> instead of Page<Product> . If I change Page to List in return type all going to be fine. Why it works this way? Is it possible to change this behavior?

I use select p, c to fill resulting products with all data from product and category by one query. Without c Hibernate doing some additional queries to get Categories.

does your repository interface extend JpaRepository or PagingAndSortingRepository , eg like this (where Long is the type of your entities @Id field:

@Repository
interface ProductRepository extends JpaRepository<Product, Long> {

    // your custom repo methods...
}

Try this

@Query("from Product p left join fetch p.category c " +
       "where (:categoryId = -1L or c.id = :categoryId) and " +
       "(:priceFrom is null or p.price >= :priceFrom) and " +
       "(:priceTo is null or p.price <= :priceTo)")
Page<Product> filterProducts(@Param("categoryId") Long categoryId,
                                     @Param("priceFrom") BigDecimal priceFrom,
                                     @Param("priceTo") BigDecimal priceTo,
                                     Pageable pageable);

In order to calculate the proper page info, Spring JPA also need the maxinum number of rows. (for calculating the page numbers). In order to get this you need to provide a countQuery in addition to the original query definition:

@Query(value = "select p, c" +
        "from Product p " +
        "left join fetch Category c on p.category.id = c.id " +
        "where (:categoryId = -1L or c.id = :categoryId) and " +
        "(:priceFrom is null or p.price >= :priceFrom) and " +
        "(:priceTo is null or p.price <= :priceTo)",
       countQuery = "select count(p.id)" +
        "from Product p " +
        "left join fetch Category c on p.category.id = c.id " +
        "where (:categoryId = -1L or c.id = :categoryId) and " +
        "(:priceFrom is null or p.price >= :priceFrom) and " +
        "(:priceTo is null or p.price <= :priceTo)",

) Page filterProducts(@Param("categoryId") Long categoryId, @Param("priceFrom") BigDecimal priceFrom, @Param("priceTo") BigDecimal priceTo, Pageable pageable);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM