dubonzi dubonzi - 1 year ago 370
Java Question

Spring Data PageImpl not returning page with the correct size?

Hi Im learning Spring MVC and Spring Data JPA and am trying to create a new Page using a List of objects retrieved from the database. First I get all the elements from the DB, convert it to a Stream and then use lambda to filter the results. Then I need a Page with a set number of elements, however, instantiating a new PageImpl doesnt seem to return a page with the correct size.

Here is my code:

List<Produtos> listaFinal;
Stream<Produtos> stream = produtosRepository.findAll().stream();
listaFinal = stream.filter(p -> p.getProdNome().contains("uio")).collect(Collectors.toList());
long total = listaFinal.size();
Page<Produtos> imp = new PageImpl<>(listaFinal,pageable,total);

Here's a screenshot from debugging:

Note the size in the Pageable object is set to 20 and it understands that it needs 4 pages to render the 70 elements, but it returns the whole list.

What am I missing?

Edit answering the comment made by Thomas:

Thanks for your answer!
I understand how to use Page to return just a slice of the data. The code I showed was my attempt to use a lambda expression to filter my collection. The problem for me is I want to use Java8's lambda to query the database via Spring Data JPA. Im used to VB.NET's and Entity
query expressions and was wondering how to do the same with Spring JPA.

In my repository, Im using
extends JpaRepository<Produtos, Integer>, QueryDslPredicateExecutor<Produtos>
which gives me access to
. However, the Predicate is not typed so I cant simply use
p -> p.getProdNome().contains("uio")
in the query.
Obs: Im using SQL Server and Hibernate.

Answer Source

After learning more about how Spring Data works I ended up using @Query annotations on my methods inside the JpaRepository implementations to properly query the DB and filter the results, eliminating the need to use a stream and then convert back to Page.

Here's how the code above would look in case anyone needs an example:

@Query("select p from Produtos p where p.prodNome = ?1")
public Page<Produtos> productsListByName(String prodNome, Pageable pageable)

Im aware of Spring's findBy methods but sometimes the method names become really difficult to read depending on the amount of parameters so I just stuck to JPQL.

Doing it this way the Page's content will always have up to the maximum amount of elements defined by you in the Spring configuration.

I also use a custom implementation of PageImpl, I'm not at work right now and don't have access to the code, but I'll post it whenever I can.

Edit: Custom implementation can be found here.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download