Pagination in Spring Data JPA (limit and offset)

后端 未结 7 843
眼角桃花
眼角桃花 2020-12-02 08:54

I want the user to be able to specify the limit (the size of the amount returned) and offset (the first record returned / index returned) in my query method.

Here a

相关标签:
7条回答
  • 2020-12-02 09:16

    You probably can't to this with spring data jpa. If the offset is very small, you might just remove the top X statements from the query after retrieval.

    Otherwise, you could define the page size to be the offset and start at page+1.

    0 讨论(0)
  • 2020-12-02 09:18

    Suppose you are filtering and soring and paging at same time Below @Query will help you

        @Query(value = "SELECT * FROM table  WHERE firstname= ?1  or lastname= ?2 or age= ?3 or city= ?4 or "
            + " ORDER BY date DESC OFFSET ?8 ROWS FETCH NEXT ?9 ROWS ONLY" , nativeQuery = true)
    List<JobVacancy> filterJobVacancyByParams(final String firstname, final String lastname,
            final String age, final float city,int offset, int limit);
    
    0 讨论(0)
  • 2020-12-02 09:21

    Below code should do it. I am using in my own project and tested for most cases.

    usage:

       Pageable pageable = new OffsetBasedPageRequest(offset, limit);
       return this.dataServices.findAllInclusive(pageable);
    

    and the source code:

    import org.apache.commons.lang3.builder.EqualsBuilder;
    import org.apache.commons.lang3.builder.HashCodeBuilder;
    import org.apache.commons.lang3.builder.ToStringBuilder;
    import org.springframework.data.domain.AbstractPageRequest;
    import org.springframework.data.domain.Pageable;
    import org.springframework.data.domain.Sort;
    
    import java.io.Serializable;
    
    /**
    * Created by Ergin
    **/
    public class OffsetBasedPageRequest implements Pageable, Serializable {
    
        private static final long serialVersionUID = -25822477129613575L;
    
        private int limit;
        private int offset;
        private final Sort sort;
    
        /**
         * Creates a new {@link OffsetBasedPageRequest} with sort parameters applied.
         *
         * @param offset zero-based offset.
         * @param limit  the size of the elements to be returned.
         * @param sort   can be {@literal null}.
         */
        public OffsetBasedPageRequest(int offset, int limit, Sort sort) {
            if (offset < 0) {
                throw new IllegalArgumentException("Offset index must not be less than zero!");
            }
    
            if (limit < 1) {
                throw new IllegalArgumentException("Limit must not be less than one!");
            }
            this.limit = limit;
            this.offset = offset;
            this.sort = sort;
        }
    
        /**
         * Creates a new {@link OffsetBasedPageRequest} with sort parameters applied.
         *
         * @param offset     zero-based offset.
         * @param limit      the size of the elements to be returned.
         * @param direction  the direction of the {@link Sort} to be specified, can be {@literal null}.
         * @param properties the properties to sort by, must not be {@literal null} or empty.
         */
        public OffsetBasedPageRequest(int offset, int limit, Sort.Direction direction, String... properties) {
            this(offset, limit, new Sort(direction, properties));
        }
    
        /**
         * Creates a new {@link OffsetBasedPageRequest} with sort parameters applied.
         *
         * @param offset zero-based offset.
         * @param limit  the size of the elements to be returned.
         */
        public OffsetBasedPageRequest(int offset, int limit) {
            this(offset, limit, Sort.unsorted());
        }
    
        @Override
        public int getPageNumber() {
            return offset / limit;
        }
    
        @Override
        public int getPageSize() {
            return limit;
        }
    
        @Override
        public int getOffset() {
            return offset;
        }
    
        @Override
        public Sort getSort() {
            return sort;
        }
    
        @Override
        public Pageable next() {
            return new OffsetBasedPageRequest(getOffset() + getPageSize(), getPageSize(), getSort());
        }
    
        public OffsetBasedPageRequest previous() {
            return hasPrevious() ? new OffsetBasedPageRequest(getOffset() - getPageSize(), getPageSize(), getSort()) : this;
        }
    
    
        @Override
        public Pageable previousOrFirst() {
            return hasPrevious() ? previous() : first();
        }
    
        @Override
        public Pageable first() {
            return new OffsetBasedPageRequest(0, getPageSize(), getSort());
        }
    
        @Override
        public boolean hasPrevious() {
            return offset > limit;
        }
    
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
    
            if (!(o instanceof OffsetBasedPageRequest)) return false;
    
            OffsetBasedPageRequest that = (OffsetBasedPageRequest) o;
    
            return new EqualsBuilder()
                    .append(limit, that.limit)
                    .append(offset, that.offset)
                    .append(sort, that.sort)
                    .isEquals();
        }
    
        @Override
        public int hashCode() {
            return new HashCodeBuilder(17, 37)
                    .append(limit)
                    .append(offset)
                    .append(sort)
                    .toHashCode();
        }
    
        @Override
        public String toString() {
            return new ToStringBuilder(this)
                    .append("limit", limit)
                    .append("offset", offset)
                    .append("sort", sort)
                    .toString();
        }
    }
    
    0 讨论(0)
  • 2020-12-02 09:25

    Here you go:

    public interface EmployeeRepository extends JpaRepository<Employee, Integer> {
    
        @Query(value="SELECT e FROM Employee e WHERE e.name LIKE ?1 ORDER BY e.id offset ?2 limit ?3", nativeQuery = true)
        public List<Employee> findByNameAndMore(String name, int offset, int limit);
    }
    
    0 讨论(0)
  • 2020-12-02 09:30

    Maybe the answer is kind of late, but I thought about the same thing. Compute the current page based on offset and limit. Well, it is not exactly the same because it "assumes" that the offset is a multiple of the limit, but maybe your application is suitable for this.

    @Override
    public List<Employee> findByName(String name, int offset, int limit) {
        // limit != 0 ;)
        int page = offset / limit;
        return repository.findByName(name, new PageRequest(page, limit));
    }
    

    I would suggest a change of the architecture. Change your controller or whatever calls the service to initially give you page and limit if possible.

    0 讨论(0)
  • 2020-12-02 09:30

    Try that:

    public interface ContactRepository extends JpaRepository<Contact, Long> 
    {
        @Query(value = "Select c.* from contacts c where c.username is not null order by c.id asc limit ?1,  ?2 ", nativeQuery = true)         
        List<Contact> findContacts(int offset, int limit);        
    }
    
    0 讨论(0)
提交回复
热议问题