spring-data-jpa
spring-data-jpa copied to clipboard
Repository returns PageImpl and executes count query when using Slice as return type [DATAJPA-1464]
Martin Möller opened DATAJPA-1464 and commented
public interface JavaUserRepositoryWithImplicitQuery extends Repository<User, Long> {
Slice<User> findAll(Pageable pageable);
}
This repository returns at runtime a PageImpl and a count query is run against the db. As far as I understand Slice and Page, this should not happen.
The linked reproducer (branch is called slice) has tests that check for SliceImpl. Relevant is only the count query and not the implementation of Slice but they seem to be related. Logging is activated where the count query can be observed
Affects: 2.1.2 (Lovelace SR2)
Reference URL: https://bitbucket.org/martinmo/spring-data-jpa-demo/src/4e2605ebfbaad16d973b6dbdc14b6d066b3a7fec/?at=slice
Is there any plans to fix this (or a workaround)? Today I faced this problem with Spring Data JPA 2.7.0
Are you saying this is still reproducible with recent releases?
yes, here is an example repo that reproduce the issue, it contains a CI pipeline that demonstrates with a test that it fails to return a SliceImpl and returns a PageImpl that contains a total size of the page which triggers the count query that I want to avoid by using Slice. https://github.com/soasada/spring-data-jpa-slice-issue
That's not a bug. You are re-declaring the method Page<T> findAll(Pageable pageable) of PagingAndSortingRepository. It's implementation, of course, has to read a PageImpl instance as it has to satisfy the contract of that method. That you re-declare the method with a super type to be returned cannot change anything about that.
The reference docs only show and explain Slice as optimization for dedicated query methods, not for re-declared CRUD methods. As a workaround you should be able to declare a similarly looking query method Slice<T> findAllBy(Pageable pageable) (note the slight difference in naming) that should behave as you suggest.
I'm not using JpaRepository or an interface extending PagingAndSortingRepository for doing that, AFAIK CrudRepository does not have the method (Page<T> findAll(Pageable pageable)) so I'm not overriding PagingAndSortingRepository.
You actually are, as in fact the JPA implementation of CrudRepository, SimpleJpaRepository implements PagingAndSortingRepository in preparation of our users declaring PASR as repository super type. Page<T> findAll(Pageable) is not a query method, and thus the optimization by using the different query method return type does not work. That's what I am trying to say.
ok, I was fooled by the implementation of the CrudRepository interface, thanks for the clarification. I will add a comment to my code to not forget that.
That said, I can see why this is not immediately obvious that a call to the method would be executed that way. However, changing that would cause significant rework to the internal routing of calls, and I am not quite sure that I currently oversee the side effects of not routing the method call through the actual implementation but essentially executing a derived query for it. I'll take this to the team for discussion.
Thanks for digging this up, though! 🙃
Since this is "worked as designed", I'm closing this ticket.