springboot 分页查询参数_springboot带分页的条件查询

QueryDSL简介

QueryDSL仅仅是一个通用的查询框架,专注于通过Java API构建类型安全的SQL查询。

Querydsl可以通过一组通用的查询API为用户构建出适合不同类型ORM框架或者是SQL的查询语句,也就是说QueryDSL是基于各种ORM框架以及SQL之上的一个通用的查询框架。

借助QueryDSL可以在任何支持的ORM框架或者SQL平台上以一种通用的API方式来构建查询。目前QueryDSL支持的平台包括JPA,JDO,SQL,Java Collections,RDF,Lucene,Hibernate Search。

官网地址:http://www.querydsl.com/static/querydsl/4.1.3/reference/html_single/

Querydsl 是一个类型安全的 Java 查询框架,支持 JPA, JDO, JDBC, Lucene, Hibernate Search 等标准。类型安全( Type safety )和一致性( Consistency )是它设计的两大准则。在 Spring Boot 中可以很好的弥补 JPA 的不灵活,实现更强大的逻辑。

1.配置到项目

第一步:Maven引入依赖:

首先对于queryDSL有两个版本,com.mysema.querydsl和com.querydsl,前者是3.X系列后者是4.X系列,这里使用的是后者.

1

2 com.querydsl

3 querydsl-apt

4 provided

5

6

7

8 com.querydsl

9 querydsl-jpa

10

第二步:加入插件,用于生成查询实例,因为是类型安全的,所以还需要加上 Maven APT plugin ,使用 APT 自动生成一些类:

1

2

3

4 ...5

6 com.mysema.maven

7 apt-maven-plugin

8 1.1.3

9

10

11 generate-sources

12

13 process

14

15

16 target/generated-sources

17 com.querydsl.apt.jpa.JPAAnnotationProcessor

18

19

20

21

22 ...23

24

25

执行mvn compile之后,可以找到该target/generated-sources/java,然后IDEA标示为源代码目录即可

3.基本概念

每一个 Model (使用  @javax.persistence.Entity  注解的), Querydsl 都会在同一个包下生成一个以 Q 开头(默认,可配置)的类,来实现便利的查询操作。

Spring 提供了一个便捷的方式使用 Querydsl ,只需要在 Repository 中继承  QueryDslPredicateExecutor 即可:

@Repositorypublic interface NoticeRespository extends JpaRepository, QueryDslPredicateExecutor{ }

然后就可以使用 UserRepository 无缝和 Querydsl 连接, QueryDslPredicateExecutor 接口提供了如下方法:

1 public interface QueryDslPredicateExecutor{2

3 T findOne(Predicate predicate);4

5 IterablefindAll(Predicate predicate);6

7 IterablefindAll(Predicate predicate, Sort sort);8

9 Iterable findAll(Predicate predicate, OrderSpecifier>... orders);10

11 Iterable findAll(OrderSpecifier>... orders);12

13 PagefindAll(Predicate predicate, Pageable pageable);14

15 longcount(Predicate predicate);16

17 booleanexists(Predicate predicate);18 }

4.Spring 参数支持解析 com.querydsl.core.types.Predicate

根据用户请求的参数自动生成 Predicate,这样搜索方法不用自己写啦,比如

1 @GetMapping("posts")2 public Object posts(@QuerydslPredicate(root = Post.class) Predicate predicate) {3 returnpostRepository.findAll(predicate);4 }5 //或者顺便加上分页

6 @GetMapping("posts")7 public Object posts(@QuerydslPredicate(root = Post.class) Predicate predicate, Pageable pageable) {8 returnpostRepository.findAll(predicate, pageable);9 }

然后请求:

/posts?title=title01 // 返回文章 title 为 title01 的文章

/posts?id=2 // 返回文章 id 为 2 的文章

/posts?category.name=Python // 返回分类为 Python 的文章(你没看错,可以嵌套,访问关系表中父类属性)

/posts?user.id=2&category.name=Java // 返回用户 ID 为 2 且分类为 Java 的文章

Pageable  是Spring Data库中定义的一个接口,该接口是所有分页相关信息的一个抽象,通过该接口,我们可以得到和分页相关所有信息(例如 pageNumber 、 pageSize 等)。

Pageable定义了很多方法,但其核心的信息只有两个:一是分页的信息( page 、 size ),二是排序的信息。

在springmvc的请求中只需要在方法的参数中直接定义一个 pageable 类型的参数,当Spring发现这个参数时,Spring会自动的根据request的参数来组装该pageable对象,Spring支持的request参数如下:

page ,第几页,从0开始,默认为第0页

size ,每一页的大小,默认为20

sort ,排序相关的信息,以property,property(,ASC|DESC)的方式组织,例如sort=firstname&sort=lastname,desc表示在按firstname正序排列基础上按lastname倒序排列。

这样,我们就可以通过url的参数来进行多样化、个性化的查询。

Spring data提供了 @PageableDefault 帮助我们个性化的设置pageable的默认配置。例如 @PageableDefault(value = 15, sort = { "id" }, direction = Sort.Direction.DESC) 表示默认情况下我们按照id倒序排列,每一页的大小为15。

1 @ResponseBody2 @RequestMapping(value = "list", method=RequestMethod.GET)3 public Page listByPageable(@PageableDefault(value = 15, sort = { "id" }, direction =Sort.Direction.DESC)4 Pageable pageable) {5 returnblogRepository.findAll(pageable);6 }

4.注意,这样不会产生 SQL 注入问题的,因为不存在的属性写了是不起效果的, Spring 已经进行了判断。

再补充一点,你还可以修改默认行为,继承 QueryDslPredicateExecutor 接口:

1 @Repository2 public interface NoticeRespository extends JpaRepository, QueryDslPredicateExecutor,QuerydslBinderCustomizer{3

4 default voidcustomize(QuerydslBindings bindings,QNotice notice){5 bindings.bind(notice.content).first((path,value) ->path.contains(value).or(notice.title.contains(value)));6 bindings.bind(notice.firsttime).first((path,value) ->notice.pushdate.after(value));7 bindings.bind(notice.secondtime).first((path,value) ->notice.pushdate.before(value));8 }9

10 }

这样你再访问 /list?content=keywords  时,返回的是文章标题包含 keywords 或者内容包含keywords,而不是仅仅等于的所有文章啦!

而且访问 /list?firsttime=2018.1.10&secontime=2018.1.11 时,返回的是pushdate在firsttime和secondtime之间的文章,只输入firsttime是之后的所有,只输入secondtime则是之前的所有文章。这样大大简化了操作!

5.实例

1 packagecom.xunao.rubber.web.admin.notice;2

3 import com.xunao.rubber.domain.*;4 importcom.xunao.rubber.repository.NoticeRespository;5 importorg.springframework.beans.factory.annotation.Autowired;6 import org.springframework.data.domain.*;7 importorg.springframework.data.querydsl.binding.QuerydslPredicate;8 importorg.springframework.data.web.PageableDefault;9 importorg.springframework.stereotype.Controller;10 importorg.springframework.ui.Model;11 import org.springframework.web.bind.annotation.*;12 importorg.springframework.data.domain.Pageable;13 importcom.querydsl.core.types.Predicate;14

15 /**

16 *@authorjinzhe17 * @date 2018/1/1018 */

19 @Controller20 @RequestMapping("/admin/notice")21 public classAdminNoticeRecordController {22

23 @Autowired24 privateNoticeRespository noticeRespository;25

26 @GetMapping("/list")27 publicString notice(Model model,Notice notice,28 @PageableDefault(sort = "id", direction =Sort.Direction.DESC) Pageable pageable,29 @QuerydslPredicate(root = Notice.class) Predicate predicate) {30 Page notices =noticeRespository.findAll(predicate, pageable);31 model.addAttribute("notices", notices);32 return "admin/notice/list";33 }34 }

predicate 除了之前在Respository里写的默认的条件外,还可以自己添加新的条件,例如:

predicate = QNotice.notice.pushdate.between(firsttime, secondtime).and(predicate);

predicate = QNotice.notice.content.contains(keywords).and(predicate);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值