SpringDataJpa基础篇3:分页与排序

1、SpringDataJpa中分页相关接口及类

1.1、Pageable接口

【Pageable接口源码】

public interface Pageable {
	
	static Pageable unpaged() {
		return Unpaged.INSTANCE;
	}
	default boolean isPaged() {
		return true;
	}
	default boolean isUnpaged() {
		return !isPaged();
	}
	int getPageNumber();
	int getPageSize();
	long getOffset();
	Sort getSort();
	default Sort getSortOr(Sort sort) {

		Assert.notNull(sort, "Fallback Sort must not be null!");

		return getSort().isSorted() ? getSort() : sort;
	}
	
	Pageable next();
	
	Pageable previousOrFirst();
	
	Pageable first();
	
	boolean hasPrevious();
	
	default Optional<Pageable> toOptional() {
		return isUnpaged() ? Optional.empty() : Optional.of(this);
	}
}

1.2、PageRequest类

PageRequest类是Pageable接口的实现类

import org.springframework.data.domain.Sort.Direction;
import org.springframework.lang.Nullable;
/**
 * Basic Java Bean implementation of {@code Pageable}.
 *上面一句话是说PageRequest是对Pageable接口的实现
 */
public class PageRequest extends AbstractPageRequest {
private static final long serialVersionUID = -4541509938956089562L;
   //排序属性
	private final Sort sort;
//@Deprecated表示该构造方法一句过期,不建议使用
	@Deprecated
	public PageRequest(int page, int size) {
		this(page, size, Sort.unsorted());
	}
//@Deprecated表示该构造方法一句过期,不建议使用
	@Deprecated
	public PageRequest(int page, int size, Direction direction, String... properties) {
		this(page, size, Sort.by(direction, properties));
	}
//@Deprecated表示该构造方法一句过期,不建议使用	
	@Deprecated
	public PageRequest(int page, int size, Sort sort) {
		super(page, size);
		this.sort = sort;
	}

	/**
	 * Creates a new unsorted {@link PageRequest}.
	 *上面一句话表示创建一个新的未排序
	 * @param page zero-based page index 当前页,是从0开始.
	 * @param size the size of the page to be returned 每页多少条记录。	
	 */
	public static PageRequest of(int page, int size) {
		return of(page, size, Sort.unsorted());
	}

	/**
	 * Creates a new {@link PageRequest} with sort parameters applied.
	 *上面一句含义创建一个带排序参数的分页
	 * @param page zero-based page index 当前页,从第0页开始.
	 * @param size the size of the page to be returned.
	 * @param sort must not be {@literal null} 设置排序.
	 * @since 2.0
	 */
	public static PageRequest of(int page, int size, Sort sort) {
		return new PageRequest(page, size, sort);
	}

	
	public static PageRequest of(int page, int size, Direction direction, String... properties) {
		return of(page, size, Sort.by(direction, properties));
	}

	
	public Sort getSort() {
		return sort;
	}
//下一页
	public Pageable next() {
		return new PageRequest(getPageNumber() + 1, getPageSize(), getSort());
	}
//上一页
	
	public PageRequest previous() {
		return getPageNumber() == 0 ? this : new PageRequest(getPageNumber() - 1, getPageSize(), getSort());
	}

//第一页是从0开始
	public Pageable first() {
		return new PageRequest(0, getPageSize(), getSort());
	}

	@Override
	public boolean equals(@Nullable Object obj) {
		if (this == obj) {
			return true;
		}
		if (!(obj instanceof PageRequest)) {
			return false;
		}
		PageRequest that = (PageRequest) obj;
		return super.equals(that) && this.sort.equals(that.sort);
	}

	@Override
	public int hashCode() {
		return 31 * super.hashCode() + sort.hashCode();
	}
	@Override
	public String toString() {
		return String.format("Page request [number: %d, size %d, sort: %s]", getPageNumber(), getPageSize(), sort);
	}
}

1.3、Page接口

Page接口其实是SpringDataJpa分页结果的一个返回值类型而已。

import java.util.Collections;
import java.util.function.Function;
public interface Page<T> extends Slice<T> {
//创建一个空的Page对象	
	static <T> Page<T> empty() {
		return empty(Pageable.unpaged());
	}
//创建一个空的Page对象,且指定pageable分页参数
	static <T> Page<T> empty(Pageable pageable) {
		return new PageImpl<>(Collections.emptyList(), pageable, 0);
	}
//返回总页数
	int getTotalPages();

//返回元素的总数
	long getTotalElements();
	//
	<U> Page<U> map(Function<? super T, ? extends U> converter);
}

2、SpringDataJpa中排序相关接口及类

2.1、Sort类中的内部类Direction

其实在Sort类中有个类部类Direction,而Direction是一个枚举类型。

	/**
	 * Enumeration for sort directions.
	 * Sort类中内部枚举类	 
	 */
	public static enum Direction {
//ASC表示升序,DESC表示降序
		ASC, DESC;
		/**
		 * Returns whether the direction is ascending.
		 * 返回一个升序
		 * @return
		 * @since 1.13
		 */
		public boolean isAscending() {
			return this.equals(ASC);
		}

		/**
		 * Returns whether the direction is descending.
		 * 返回一个降序
		 * @return
		 * @since 1.13
		 */
		public boolean isDescending() {
			return this.equals(DESC);
		}
		
		public static Direction fromString(String value) {

			try {
				return Direction.valueOf(value.toUpperCase(Locale.US));
			} catch (Exception e) {
				throw new IllegalArgumentException(String.format(
						"Invalid value '%s' for orders given! Has to be either 'desc' or 'asc' (case insensitive).", value), e);
			}
		}
		
		public static Optional<Direction> fromOptionalString(String value) {

			try {
				return Optional.of(fromString(value));
			} catch (IllegalArgumentException e) {
				return Optional.empty();
			}
		}
	}

2.2、Order类

Order类是Sort类的一个内部类

//sort类的一个内部类
	public static class Order implements Serializable {
		private static final long serialVersionUID = 1522511010900108987L;
		private static final boolean DEFAULT_IGNORE_CASE = false;
		private static final NullHandling DEFAULT_NULL_HANDLING = NullHandling.NATIVE;
		private final Direction direction;
		private final String property;
		private final boolean ignoreCase;
		private final NullHandling nullHandling;
		public Order(@Nullable Direction direction, String property) {
			this(direction, property, DEFAULT_IGNORE_CASE, DEFAULT_NULL_HANDLING);
		}

		public Order(@Nullable Direction direction, String property, NullHandling nullHandlingHint) {
			this(direction, property, DEFAULT_IGNORE_CASE, nullHandlingHint);
		}
		
		@Deprecated
		public Order(String property) {
			this(DEFAULT_DIRECTION, property);
		}

		
		public static Order by(String property) {
			return new Order(DEFAULT_DIRECTION, property);
		}

		public static Order asc(String property) {
			return new Order(Direction.ASC, property, DEFAULT_NULL_HANDLING);
		}

		
		public static Order desc(String property) {
			return new Order(Direction.DESC, property, DEFAULT_NULL_HANDLING);
		}

		private Order(@Nullable Direction direction, String property, boolean ignoreCase, NullHandling nullHandling) {

			if (!StringUtils.hasText(property)) {
				throw new IllegalArgumentException("Property must not null or empty!");
			}

			this.direction = direction == null ? DEFAULT_DIRECTION : direction;
			this.property = property;
			this.ignoreCase = ignoreCase;
			this.nullHandling = nullHandling;
		}

		public Direction getDirection() {
			return direction;
		}

		public String getProperty() {
			return property;
		}

	
		public boolean isAscending() {
			return this.direction.isAscending();
		}

		public boolean isDescending() {
			return this.direction.isDescending();
		}

	
		public boolean isIgnoreCase() {
			return ignoreCase;
		}

		
		public Order with(Direction direction) {
			return new Order(direction, this.property, this.ignoreCase, this.nullHandling);
		}

	
		public Order withProperty(String property) {
			return new Order(this.direction, property, this.ignoreCase, this.nullHandling);
		}

		public Sort withProperties(String... properties) {
			return Sort.by(this.direction, properties);
		}

		public Order ignoreCase() {
			return new Order(direction, property, true, nullHandling);
		}

		public Order with(NullHandling nullHandling) {
			return new Order(direction, this.property, ignoreCase, nullHandling);
		}

		public Order nullsFirst() {
			return with(NullHandling.NULLS_FIRST);
		}

		public Order nullsLast() {
			return with(NullHandling.NULLS_LAST);
		}

	
		public Order nullsNative() {
			return with(NullHandling.NATIVE);
		}

		public NullHandling getNullHandling() {
			return nullHandling;
		}

		@Override
		public int hashCode() {

			int result = 17;

			result = 31 * result + direction.hashCode();
			result = 31 * result + property.hashCode();
			result = 31 * result + (ignoreCase ? 1 : 0);
			result = 31 * result + nullHandling.hashCode();

			return result;
		}

		@Override
		public boolean equals(@Nullable Object obj) {

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

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

			Order that = (Order) obj;

			return this.direction.equals(that.direction) && this.property.equals(that.property)
					&& this.ignoreCase == that.ignoreCase && this.nullHandling.equals(that.nullHandling);
		}

		
		@Override
		public String toString() {

			String result = String.format("%s: %s", property, direction);

			if (!NullHandling.NATIVE.equals(nullHandling)) {
				result += ", " + nullHandling;
			}

			if (ignoreCase) {
				result += ", ignoring case";
			}

			return result;
		}
	}

2.3、Sort排序类

【Sort类的部分源码】

public class Sort implements Streamable<org.springframework.data.domain.Sort.Order>, Serializable {

	private static final long serialVersionUID = 5737186511678863905L;
//
	private static final Sort UNSORTED = Sort.by(new Order[0]);

	public static final Direction DEFAULT_DIRECTION = Direction.ASC;

	private final List<Order> orders;
//@Deprecated注解表示该方法已经过期,官方不推荐使用
	@Deprecated
	public Sort(Order... orders) {
		this(Arrays.asList(orders));
	}
//@Deprecated注解表示该方法已经过期,官方不推荐使用
	@Deprecated
	public Sort(List<Order> orders) {

		Assert.notNull(orders, "Orders must not be null!");

		this.orders = Collections.unmodifiableList(orders);
	}
//@Deprecated注解表示该方法已经过期,官方不推荐使用
	@Deprecated
	public Sort(String... properties) {
		this(DEFAULT_DIRECTION, properties);
	}

	
	public Sort(Direction direction, String... properties) {
		this(direction, properties == null ? new ArrayList<>() : Arrays.asList(properties));
	}

	
	public Sort(Direction direction, List<String> properties) {

		if (properties == null || properties.isEmpty()) {
			throw new IllegalArgumentException("You have to provide at least one property to sort by!");
		}

		this.orders = new ArrayList<>(properties.size());

		for (String property : properties) {
			this.orders.add(new Order(direction, property));
		}
	}

	
	public static Sort by(String... properties) {

		Assert.notNull(properties, "Properties must not be null!");

		return properties.length == 0 ? Sort.unsorted() : new Sort(properties);
	}

	public static Sort by(List<Order> orders) {

		Assert.notNull(orders, "Orders must not be null!");

		return orders.isEmpty() ? Sort.unsorted() : new Sort(orders);
	}

	
	public static Sort by(Order... orders) {

		Assert.notNull(orders, "Orders must not be null!");

		return new Sort(orders);
	}

	
	public static Sort by(Direction direction, String... properties) {

		Assert.notNull(direction, "Direction must not be null!");
		Assert.notNull(properties, "Properties must not be null!");
		Assert.isTrue(properties.length > 0, "At least one property must be given!");

		return Sort.by(Arrays.stream(properties)//
				.map(it -> new Order(direction, it))//
				.collect(Collectors.toList()));
	}

	public static Sort unsorted() {
		return UNSORTED;
	}


	public Sort descending() {
		return withDirection(Direction.DESC);
	}

	
	public Sort ascending() {
		return withDirection(Direction.ASC);
	}

	public boolean isSorted() {
		return !orders.isEmpty();
	}

	public boolean isUnsorted() {
		return !isSorted();
	}
//.............................其他方法及内部类代码省略...................................
}

3、应用例子

3.1、实体类

@Entity
@Table(name="tb_label")
public class Label implements Serializable {
    @Id
    private String id;//
    private String labelname;//标签名称
    private String state;//状态
    private Long count;//使用数量
    private Long fans;//关注数
    private String recommend;//是否推荐
    public Label() {
    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getLabelname() {
        return labelname;
    }
    public void setLabelname(String labelname) {
        this.labelname = labelname;
    }
    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public Long getCount() {
        return count;
    }

    public void setCount(Long count) {
        this.count = count;
    }
    public Long getFans() {
        return fans;
    }
    public void setFans(Long fans) {
        this.fans = fans;
    }
    public String getRecommend() {
        return recommend;
    }
    public void setRecommend(String recommend) {
        this.recommend = recommend;
    }
    @Override
    public String toString() {
        return "Label{" +
                "id='" + id + '\'' +
                ", labelname='" + labelname + '\'' +
                ", state='" + state + '\'' +
                ", count=" + count +
                ", fans=" + fans +
                ", recommend='" + recommend + '\'' +
                '}';
    }
}

3.2、DAO接口

/**
 * JpaRepository基本增删改查操作
 * JpaSpecificationExecutor用于复杂查询
 */
public interface LabelDao extends JpaRepository<Label,String>, JpaSpecificationExecutor<Label> {
}

3.3、测试代码

@RunWith(SpringRunner.class)
@SpringBootTest(classes = BaseApplication.class)
public class JpaTest {
    @Autowired
    private LabelDao labelDao;
    @Test
    public void testPage(){
        int pageNo=2;//第二页,注意在springdatajpa中分页是从第0页开始
        int size=5;//每页5条
        //PageRequest类是Pageable接口的实现类
        PageRequest pageRequest =  PageRequest.of(pageNo-1, size);
        Page<Label> page = labelDao.findAll(pageRequest);
        System.err.println("-----------------总记录数:"+page.getTotalElements());
        System.err.println("------------------总页数:"+page.getTotalPages());
        System.err.println("------------------当前第几页:"+page.getNumber());
        System.err.println("------------------当前页面的List数据集:"+page.getContent());
        System.out.println("------------------当前页的记录数:"+page.getNumberOfElements());
    }
    @Test
    public void testPageAndSort(){
       //设置排序字段,该字段是实体类中属性,不是数据库中的列
       Sort sort=new Sort(Sort.Direction.DESC,"id");
        int pageNo=1;//第二页,注意在springdatajpa中分页是从第0页开始
        int size=5;//每页5条
        //PageRequest类是Pageable接口的实现类
        PageRequest pageRequest =  PageRequest.of(pageNo-1, size,sort);
        Page<Label> page = labelDao.findAll(pageRequest);
        System.out.println("------------------总记录数:"+page.getTotalElements());
        System.out.println("------------------总页数:"+page.getTotalPages());
        System.out.println("------------------当前第几页:"+page.getNumber());
        System.out.println("------------------当前页面的List数据集:"+page.getContent());
        System.out.println("------------------当前页的记录数:"+page.getNumberOfElements());
    }
}

猜你喜欢

转载自blog.csdn.net/u013089490/article/details/84973133
今日推荐