Spring Data JPA 分页

本文探讨了Spring Data JPA中的分页实现,通过分析源码揭示了分页信息如何从高层传递到DAO层,最终形成SQL的LIMIT语句。主要涉及Pageable接口、Slice和Page类,以及AbstractPageRequest和PageRequest的使用。

最近在学习Spring Data JPA,    用到了 Spring-data-commons包中自带的分页工具,

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;

public interface CommentRepository extends JpaRepository<Comment,Integer> {

    @Override
        Page<Comment> findAll(Pageable pageable);
}

抱着学习的心态看了下源码,是为了了解别人的实现思路, 在这里记录一下。


1.  总的来说,分页是实现了将想要请求的   pageIndex, pagesize  或者其他分页信息层层传递到dao层,

执行了一行类似下面的sql (mysql) ,并将数据返回给前端的过程。

limit关键字:LIMIT [offset,] rows

offset 是偏移量 默认是0 ,  rows是要查的行数

select * from table limit 0,5          查询前五行数据

select * from table  limit 5            查询前五行数据   因为偏移量默认是零 

select * from table_name limit 10,5         查询第11 到15 的数据     


2.  其中主要包含了以下接口和类

接口: 1.   pageable  自定义的一个接口

      2. Slice<T>    继承了 Iterable<T>

      3. Page<T>     继承了 Slice<T>

类 :   1.  AbstractPageRequest  实现了 Pageable, Serializable

        2.   PageRequest 继承了 AbstractPageRequest


3.  接口: pageable  定义了“ 实现记录分页信息的类所需要实现的方法 ” 。

package org.springframework.data.domain;

/**
 * Abstract interface for pagination information.
 * 
 * @author Oliver Gierke
 */
public interface Pageable {

	/**
	 * Returns the page to be returned.
	 * 
	 * @return the page to be returned.
	 */
	int getPageNumber(); //获得当前的页码 
        
	/**
	 * Returns the number of items to be returned.
	 * 
	 * @return the number of items of that page
	 */
	int getPageSize();  //获得一页的行数。
      
	/**
	 * Returns the offset to be taken according to the underlying page and page size.
	 * 
	 * @return the offset to be taken
	 */
	int getOffset();    //获得偏移量,即上面提到的sql里的offset , 即 页码*一页的行数  
                            //比如每页是五行数据,现在在第4页(0是第一页)则offset为20   显示索引20-24的数据
	/**
	 * Returns the sorting parameters.
	 * 
	 * @return
	 */
	Sort getSort();    //

	/**
	 * Returns the {@link Pageable} requesting the next {@link Page}.
	 * 
	 * @return
	 */
	Pageable next();     //下一页

	/**
	 * Returns the previous {@link Pageable} or the first {@link Pageable} if the current one already is the first one.
	 * 
	 * @return
	 */
	Pageable previousOrFirst();  //如果是第一页,返回第一页,如果不是,返回上一页。

	/**
	 * Returns the {@link Pageable} requesting the first page.
	 * 
	 * @return
	 */
	Pageable first();         //第一页

	/**
	 * Returns whether there's a previous {@link Pageable} we can access from the current one. Will return
	 * {@literal false} in case the current {@link Pageable} already refers to the first page.
	 * 
	 * @return
	 */
	boolean hasPrevious();    //有上一页吗
}

4.  AbstractPageRequest         pageable 的一个实现类


public abstract class AbstractPageRequest implements Pageable, Serializable {

	private static final long serialVersionUID = 1232825578694716871L;

	private final int page;      //记录页码
	private final int size;      //记录一页的行数 

	/**
	 * Creates a new {@link AbstractPageRequest}. Pages are zero indexed, thus providing 0 for {@code page} will return
	 * the first page.
	 * 
	 * @param page must not be less than zero.
	 * @param size must not be less than one.
	 */
	public AbstractPageRequest(int page, int size) {  
        //构造函数
		if (page < 0) {
			throw new IllegalArgumentException("Page index must not be less than zero!");
		}

		if (size < 1) {
			throw new IllegalArgumentException("Page size must not be less than one!");
		}

		this.page = page;
		this.size = size;
	}

	/* 
	 * (non-Javadoc)
	 * @see org.springframework.data.domain.Pageable#getPageSize()
	 */
         public int getPageSize() { 
		return size;  //返回一页的行数
	}

	/* 
	 * (non-Javadoc)
	 * @see org.springframework.data.domain.Pageable#getPageNumber()
	 */
	public int getPageNumber() {
		return page;  // 返回当前页码
	}

	/* 
	 * (non-Javadoc)
	 * @see org.springframework.data.domain.Pageable#getOffset()
	 */
	public int getOffset() {
		return page * size;   //返回偏移量
	}

	/* 
	 * (non-Javadoc)
	 * @see org.springframework.data.domain.Pageable#hasPrevious()
	 */
	public boolean hasPrevious() {
		return page > 0;       //只要不是0 就有上一页
	}

	/* 
	 * (non-Javadoc)
	 * @see org.springframework.data.domain.Pageable#previousOrFirst()
	 */
	public Pageable previousOrFirst() {
		return hasPrevious() ? previous() : first();    //..
	}

	/* 
	 * (non-Javadoc)
	 * @see org.springframework.data.domain.Pageable#next()
	 */
	public abstract Pageable next();       //未实现

	/**
	 * Returns the {@link Pageable} requesting the previous {@link Page}.
	 * 
	 * @return
	 */
	public abstract Pageable previous();     //未实现

	/* 
	 * (non-Javadoc)
	 * @see org.springframework.data.domain.Pageable#first()
	 */
	public abstract Pageable first();         //未实现

	/* 
	 * (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {                      

		final int prime = 31;
		int result = 1;

		result = prime * result + page;
		result = prime * result + size;

		return result;
	}

	/* 
	 * (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {

		if (this == obj) {
			return true;
		}

		if (obj == null || getClass() != obj.getClass()) {
			return false;
		}

		AbstractPageRequest other = (AbstractPageRequest) obj;
		return this.page == other.page && this.size == other.size;
	}
}

5.  PageRequest 继承了 AbstractPageRequest       

  

public class PageRequest extends AbstractPageRequest {

	private static final long serialVersionUID = -4541509938956089562L;

	private final Sort sort;

	/**
	 * Creates a new {@link PageRequest}. Pages are zero indexed, thus providing 0 for {@code page} will return the first
	 * page.
	 * 
	 * @param page zero-based page index.
	 * @param size the size of the page to be returned.
	 */
	public PageRequest(int page, int size) {   // 请求的页码 以及 每页的行数
		this(page, size, null);
	}

	/**
	 * Creates a new {@link PageRequest} with sort parameters applied.
	 * 
	 * @param page zero-based page index.
	 * @param size the size of the page 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 PageRequest(int page, int size, Direction direction, String... properties) {
		this(page, size, new Sort(direction, properties));
	}

	/**
	 * Creates a new {@link PageRequest} with sort parameters applied.
	 * 
	 * @param page zero-based page index.
	 * @param size the size of the page to be returned.
	 * @param sort can be {@literal null}.
	 */
	public PageRequest(int page, int size, Sort sort) {
		super(page, size);
		this.sort = sort;
	}

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.domain.Pageable#getSort()
	 */
	public Sort getSort() {
		return sort;
	}

	/* 
	 * (non-Javadoc)
	 * @see org.springframework.data.domain.Pageable#next()
	 */
	public Pageable next() {
		return new PageRequest(getPageNumber() + 1, getPageSize(), getSort());   //翻到下一页
	}

	/* 
	 * (non-Javadoc)
	 * @see org.springframework.data.domain.AbstractPageRequest#previous()
	 */
	public PageRequest previous() {
		return getPageNumber() == 0 ? this : new PageRequest(getPageNumber() - 1, getPageSize(), getSort());  //如果第一页返回自己,如果不是返回上一页
	}

	/* 
	 * (non-Javadoc)
	 * @see org.springframework.data.domain.Pageable#first()
	 */
	public Pageable first() {
		return new PageRequest(0, getPageSize(), getSort());      //返回到第一页
	}

	/*
	 * (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(final Object obj) {

		if (this == obj) {
			return true;
		}

		if (!(obj instanceof PageRequest)) {
			return false;
		}

		PageRequest that = (PageRequest) obj;

		boolean sortEqual = this.sort == null ? that.sort == null : this.sort.equals(that.sort);

		return super.equals(that) && sortEqual;
	}

	/*
	 * (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		return 31 * super.hashCode() + (null == sort ? 0 : sort.hashCode());
	}

	/* 
	 * (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return String.format("Page request [number: %d, size %d, sort: %s]", getPageNumber(), getPageSize(),
				sort == null ? null : sort.toString());
	}
}


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值