SpringBoot第二讲利用Spring Data JPA实现数据库的访问(二)_分页和JpaSpecificationExecutor接口介绍
2016-12-01 00:33
881 查看
我们继续研究spring jpa data,首先看看分页和排序的实现,在原来的代码中,我们如果希望实现分页,首先得创建一个
- PagingAndSortingRepository
- Pageable
- Page
PagingAndSortingRepository是spring data jpa实现分页的工厂,用法和Repository完全一致,先看看源码
第二个
Pageable是一个接口,它的实现类是
接下实现以下分页的操作, 创建一个
虽然PagingAndSortingRepository接口中只有findAll方法,但是我们依然可以使用Repository中的衍生查询,我们只要把Pageable放到最后一个参数即可。测试代码
分页的方法非常的简单,下面我们来实现一下排序的操作,排序和分页类似,我们需要传递一个Sort对象进去,
看看排序的代码
如果希望在分页的时候进行排序,一样也非常容易,看一下下面PageReques的构造函数
看到这里我相信大家已经会各种排序操作了,这里就不演示了,但是在实际的开发中我们还需要对排序和分页操作进行一下封装,让操作更方便一些,这个话题我们在后面的章节再来详细介绍。
Spring data jpa 在PagingAndSortingRepository接口下还提供了一个
Spring Data Jpa同样提供了类似Hibernated 的Criteria的查询方式,要使用这种方式只要继承
该接口通过Specification来定义查询条件,很多朋友可能使用的方式都是基于SQL的,对这种方式可能不太习惯,在下一讲中将会对Specification进行一下封装,让查询操作变得更加的简单方便。这里先简单看一下示例。
使用Specification的要点就是CriteriaBuilder,通过这个对象来创建条件,之后返回一个Predicate对象。这个对象中就有了相应的查询需求,我们同样可以定义多个Specification,之后通过Specifications对象将其连接起来。以下是一个非常典型的应用
这个代码生成的sql是
另外在
Pager的对象,在这个对象中记录
total(总数),totalPager(总页数),pageSize(每页多少条记录),pageIndex(当前第几页),offset(查询时的offset),在Spring Data JPA中实现分页需要用到三个接口
- PagingAndSortingRepository
- Pageable
- Page
PagingAndSortingRepository是spring data jpa实现分页的工厂,用法和Repository完全一致,先看看源码
@NoRepositoryBean public interface PagingAndSortingRepository<T, ID extends Serializable> extends CrudRepository<T, ID> { Iterable<T> findAll(Sort var1); Page<T> findAll(Pageable var1); }
第二个
findAll方法就是实现分页的方法,参数是
Pageable类型,同参数传入当前的分页对象(如:第几页,每页多少条记录,排序信息等),查询完成之后会返回一个
Page的对象。
Page对象中就存储了所有的分页信息。Pageable的源码如下
public interface Pageable { int getPageNumber(); int getPageSize(); int getOffset(); Sort getSort(); Pageable next(); Pageable previousOrFirst(); Pageable first(); boolean hasPrevious(); }
Pageable是一个接口,它的实现类是
PageRequest,PageRequest有三个构造方法
//这个构造出来的分页对象不具备排序功能 public PageRequest(int page, int size) { this(page, size, (Sort)null); } //Direction和properties用来做排序操作 public PageRequest(int page, int size, Direction direction, String... properties) { this(page, size, new Sort(direction, properties)); } //自定义一个排序的操作 public PageRequest(int page, int size, Sort sort) { super(page, size); this.sort = sort; }
Page实现了一个Slice的接口,通过这个接口获取排序之后的各个数值,这些方法都比较直观,通过名称就差不多知道该是什么样的一个操作了,大家可以自行查阅一下Page和Slice的源码,这里就不列出了。
接下实现以下分页的操作, 创建一个
StudentPageRepository来实现分页操作。
public interface StudentPageRepository extends PagingAndSortingRepository<Student,Integer> { Page<Student> findByAge(int age, Pageable pageable); }
虽然PagingAndSortingRepository接口中只有findAll方法,但是我们依然可以使用Repository中的衍生查询,我们只要把Pageable放到最后一个参数即可。测试代码
@Test public void testPage() { //显示第1页每页显示3条 PageRequest pr = new PageRequest(1,3); //根据年龄进行查询 Page<Student> stus = studentPageRepository.findByAge(22,pr); Assert.assertEquals(2,stus.getTotalPages()); Assert.assertEquals(6,stus.getTotalElements()); Assert.assertEquals(1,stus.getNumber()); }
分页的方法非常的简单,下面我们来实现一下排序的操作,排序和分页类似,我们需要传递一个Sort对象进去,
Sort是一排序类,首先有一个内部枚举对象
Direction,
Direction中有两个值
ASC和DESC分别用来确定升序还是降序,
Sort还有一个内部类
Order,
Order有有两个比较重要的属性
Sort.Direction和
property,第一个用来确定排序的方向,第二个就是排序的属性。
Sort有如下几个构造函数
//可以输入多个Sort.Order对象,在进行多个值排序时有用 public Sort(Sort.Order... orders) //和上面的方法一样,无非把多个参数换成了一个List public Sort(List<Sort.Order> orders) //当排序方向固定时,使用这个比较方便,第一个参数是排序方向,第二个开始就是排序的字段,还有一个方法第二个参数是list,原理相同 public Sort(Sort.Direction direction, String... properties)
看看排序的代码
public interface StudentPageRepository extends PagingAndSortingRepository<Student,Integer> { Page<Student> findByAge(int age, Pageable pageable); List<Student> findByAge(int age, Sort sort); } //排序的实现代码 @Test public void testSort() { //设置排序方式为name降序 List<Student> stus = studentPageRepository.findByAge(22 ,new Sort(Sort.Direction.DESC,"name")); Assert.assertEquals(5,stus.get(0).getId()); //设置排序以name和address进行升序 stus = studentPageRepository.findByAge(22 ,new Sort(Sort.Direction.ASC,"name","address")); Assert.assertEquals(8,stus.get(0).getId()); //设置排序方式以name升序,以address降序 Sort sort = new Sort( new Sort.Order(Sort.Direction.ASC,"name"), new Sort.Order(Sort.Direction.DESC,"address")); stus = studentPageRepository.findByAge(22,sort); Assert.assertEquals(7,stus.get(0).getId()); }
如果希望在分页的时候进行排序,一样也非常容易,看一下下面PageReques的构造函数
public PageRequest(int page, int size, Direction direction, String... properties) { this(page, size, new Sort(direction, properties) b89f ); } public PageRequest(int page, int size, Sort sort) { super(page, size); this.sort = sort; }
看到这里我相信大家已经会各种排序操作了,这里就不演示了,但是在实际的开发中我们还需要对排序和分页操作进行一下封装,让操作更方便一些,这个话题我们在后面的章节再来详细介绍。
Spring data jpa 在PagingAndSortingRepository接口下还提供了一个
JpaRepository接口,该接口封装了更常用的一些方法,使用方式都类似,如果将来在实现的过程中没有特殊的需求(如:不希望公开所有接口方法之类的需求),一般都继承JPARepository来操作。
Spring Data Jpa同样提供了类似Hibernated 的Criteria的查询方式,要使用这种方式只要继承
JpaSpecificationExecutor,该接口提供了如下一些方法
T findOne(Specification<T> var1); List<T> findAll(Specification<T> var1); Page<T> findAll(Specification<T> var1, Pageable var2); List<T> findAll(Specification<T> var1, Sort var2); long count(Specification<T> var1);
该接口通过Specification来定义查询条件,很多朋友可能使用的方式都是基于SQL的,对这种方式可能不太习惯,在下一讲中将会对Specification进行一下封装,让查询操作变得更加的简单方便。这里先简单看一下示例。
@Test public void testSpecificaiton() { List<Student> stus = studentSpecificationRepository.findAll(new Specification<Student>() { @Override public Predicate toPredicate(Root<Student> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) { //root.get("address")表示获取address这个字段名称,like表示执行like查询,%zt%表示值 Predicate p1 = criteriaBuilder.like(root.get("address"), "%zt%"); Predicate p2 = criteriaBuilder.greaterThan(root.get("id"),3); //将两个查询条件联合起来之后返回Predicate对象 return criteriaBuilder.and(p1,p2); } }); Assert.assertEquals(2,stus.size()); Assert.assertEquals("oo",stus.get(0).getName()); }
使用Specification的要点就是CriteriaBuilder,通过这个对象来创建条件,之后返回一个Predicate对象。这个对象中就有了相应的查询需求,我们同样可以定义多个Specification,之后通过Specifications对象将其连接起来。以下是一个非常典型的应用
@Test public void testSpecificaiton2() { //第一个Specification定义了两个or的组合 Specification<Student> s1 = new Specification<Student>() { @Override public Predicate toPredicate(Root<Student> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) { Predicate p1 = criteriaBuilder.equal(root.get("id"),"2"); Predicate p2 = criteriaBuilder.equal(root.get("id"),"3"); return criteriaBuilder.or(p1,p2); } }; //第二个Specification定义了两个or的组合 Specification<Student> s2 = new Specification<Student>() { @Override public Predicate toPredicate(Root<Student> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) { Predicate p1 = criteriaBuilder.like(root.get("address"),"zt%"); Predicate p2 = criteriaBuilder.like(root.get("name"),"foo%"); return criteriaBuilder.or(p1,p2); } }; //通过Specifications将两个Specification连接起来,第一个条件加where,第二个是and List<Student> stus = studentSpecificationRepository.findAll(Specifications.where(s1).and(s2)); Assert.assertEquals(1,stus.size()); Assert.assertEquals(3,stus.get(0).getId()); }
这个代码生成的sql是
select * from t_student where (id=2 or id=3) and (address like 'zt%' and name like 'foo%'),这其实是一个非常典型的应用,但是相信大家已经发现这个操作实在是太繁杂了,所以个人认为
Specification这个方案其实就是为了让我们对其进行封装,而不是直接使用的。
另外在
toPredicate中还有一个
CriteriaQuery的参数,这个对象提供了更多有用的查询,如分组之类的,可以使用该对象组成复杂的SQL语句来查询,这块内容和具体的封装实现将会在下一章节介绍。
相关文章推荐
- SpringBoot第二讲 利用Spring Data JPA实现数据库的访问(二)_分页和JpaSpecificationExecutor接口介绍
- SpringBoot第二讲 利用Spring Data JPA实现数据库的访问(二)_分页和JpaSpecificationExecutor接口介绍
- SpringBoot第二讲利用Spring Data JPA实现数据库的访问(一)
- SpringBoot第二讲 利用Spring Data JPA实现数据库的访问(一)
- 结合SpringDataJPA中的PagingAndSortingRepository和 JpaSpecificationExecutor接口实现大数据量的数据分页查询
- SpringBoot第二讲 利用Spring Data JPA实现数据库的访问(一)
- spring data jpa中继承JpaSpecificationExecutor接口的接口不会被IOC容器所管理
- 【SpringData】轻松愉快之玩转SpringData( 第5章 JpaSpecificationExecutor接口 第6章 课程总结 )
- spring data 接口之 JpaRepository,JpaSpecificationExecutor
- spring data 接口之 JpaRepository,JpaSpecificationExecutor
- Spring Data JPA(2)--利用PagingAndSortingRespository实现分页和排序
- Spring boot data JPA 自定义JPQL语句,以及PagingAndSortingRepository接口实现分页查询
- spring data jpa 利用JpaSpecificationExecutor做复杂查询
- spring data 接口之 JpaRepository,JpaSpecificationExecutor
- spring data 接口之 JpaRepository,JpaSpecificationExecutor
- Spring Boot Data JPA JpaSpecificationExecutor
- springBoot+easyui +spring data JPA 实现分页
- php利用msqli访问数据库并实现分页,
- Spring Data Jpa+SpringMVC+Jquery.pagination.js实现分页示例
- Spring Data Jpa - EasyUi Datagrid 分页简单实现(一)