最近在学习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());
}
}

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

被折叠的 条评论
为什么被折叠?



