Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
Artur- opened this issue Jan 13, 2023 · 10 comments
Assignees
Labels
status: superseded An issue that has been superseded by another type: enhancement A general enhancement

Comments

@Artur-
Copy link

Artur- commented Jan 13, 2023

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?

@christophstrobl
Copy link
Member

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

@christophstrobl christophstrobl added type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged labels Jan 16, 2023
@Dylan0405
Copy link

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

@gedankennebel
Copy link

gedankennebel commented Apr 12, 2023

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.

@Dylan0405
Copy link

Dylan0405 commented Apr 14, 2023

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);
}`

@membersound
Copy link

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

@ManeeshSharma17
Copy link

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

@christophstrobl christophstrobl self-assigned this Feb 23, 2024
@kmeyer-mbs
Copy link

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

Any updates on this? Thanks.

@max-buildops
Copy link

If you use MySQL (other DBs might have it as well), your second query could be a super cheap one: SELECT FOUND_ROWS();
Assuming your original statement has LIMIT as part of your select (SELECT ... LIMIT pageSize), above subsequent query returns a number of rows that would be returned if there was no LIMIT clause.
https://dev.mysql.com/doc/refman/8.4/en/information-functions.html#function_found-rows

Hope this helps.

@membersound
Copy link

@ Spring-Team: could the found_rows() function be a better alternative to the implicit executed count()? Maybe by activation with a parameter on the Repository or class-method?

@mp911de
Copy link
Member

mp911de commented Jan 31, 2025

Fixed via #3727

@mp911de mp911de closed this as completed Jan 31, 2025
@mp911de mp911de added the status: superseded An issue that has been superseded by another label Jan 31, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: superseded An issue that has been superseded by another type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

10 participants