spring-data-jpa icon indicating copy to clipboard operation
spring-data-jpa copied to clipboard

Add the possibility to fetch using Specification and Pageable but without doing a count query

Open Artur- opened this issue 2 years ago • 9 comments

If you use Page<T> findAll(Pageable pageable) then Spring Data will execute the select plus the count query for every call. To get rid of the count query when you do not need the total count, you can add a find by without any filters: List<T> findBy(Pageable pageable). You cannot add a List<T> findAll(Pageable pageable) as it will conflict with findAll that returns a Page<T>.

However when you use a Specification for filtering you still would want the same possibility: to get rid of the count query. The available findAll is Page<T> findAll(Specification<T> spec, Pageable pageable) which again prevents adding a List<T> findAll(Specification<T> spec, Pageable pageable). Also it seems that the findBy "hack" cannot be used as a method like List<T> findBy(Specification<T> filter, Pageable pageable); will throw

org.springframework.dao.InvalidDataAccessApiUsageException: At least 1 parameter(s) provided but only 0 parameter(s) present in query

Is there another way to accomplish this or could it be added as a feature?

Artur- avatar Jan 13 '23 08:01 Artur-

We could enhance the FetchableFluentQuery API to cover that usecase returning a Slice instead of a Page.

christophstrobl avatar Jan 16 '23 15:01 christophstrobl

could anybody tell me that has this problem solved or how could I realize this feature?

Dylan0405 avatar Apr 11 '23 02:04 Dylan0405

We also tried and searched everything to use Specifiactions along with a sql limit. Unfortunatley no method seems to offer us this usecase. Eventually we ended up with a custom repository method implemention, described like in the spring jpa documenation. In the implemenation we extended from SimpleJpaRepository and could make use of the getQuery(..) method.

   @Override
    public List<Event> findAllEvents(Specification<Event> specification, Sort sort, int limit) {
        var query = getQuery(specification, sort);

        if (limit > 0) {
            query.setMaxResults(limit);
        }
        return query.getResultList();
    }

Note that Event is our entity object and nothing Spring related.

gedankennebel avatar Apr 12 '23 13:04 gedankennebel

yeah, finally, I also ended up with a custom repository method implemention. Just like https://gist.github.com/tcollins/0ebd1dfa78028ecdef0b. displayed. `
@Override public Slice<T> findAllSliced(Specification<T> spec, Pageable pageable) { TypedQuery<T> query = getQuery(spec, pageable.getSort());

    query.setFirstResult((int) pageable.getOffset());
    int extraSize = pageable.getPageSize() + 1;
    query.setMaxResults(extraSize);

    List<T> result = query.getResultList();
    boolean hasNext = result.size() == extraSize;

    if(hasNext){
        result.remove(extraSize - 1);
    }
    return new SliceImpl<>(result, pageable, hasNext);
}`

Dylan0405 avatar Apr 14 '23 08:04 Dylan0405

Please also cover this for QuerydslPredicateExecutor.findBy(Predicate predicate, Function<FluentQuery.FetchableFluentQuery<S>, R> queryFunction).

membersound avatar Sep 13 '23 12:09 membersound

yeah, finally, I also ended up with a custom repository method implemention. Just like https://gist.github.com/tcollins/0ebd1dfa78028ecdef0b. displayed. ` @OverRide public Slice findAllSliced(Specification spec, Pageable pageable) { TypedQuery query = getQuery(spec, pageable.getSort());

    query.setFirstResult((int) pageable.getOffset());
    int extraSize = pageable.getPageSize() + 1;
    query.setMaxResults(extraSize);

    List<T> result = query.getResultList();
    boolean hasNext = result.size() == extraSize;

    if(hasNext){
        result.remove(extraSize - 1);
    }
    return new SliceImpl<>(result, pageable, hasNext);
}`

This is escaping some records in the result set

ManeeshSharma17 avatar Feb 23 '24 09:02 ManeeshSharma17

We could enhance the FetchableFluentQuery API to cover that usecase returning a Slice instead of a Page.

Any updates on this? Thanks.

kmeyer-mbs avatar Jun 11 '24 12:06 kmeyer-mbs