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.