spring data jpa实现多条件查询(分页和不分页)
目前的spring data jpa已经帮我们干了CRUD的大部分活了,但如果有些活它干不了(CrudRepository接口中没定义),那么只能由我们自己干了。这里要说的就是在它的框架里,如何实现自己定制的多条件查询。下面以我的例子说明一下:业务场景是我现在有张订单表,我想要支持根据订单状态、订单当前处理人和订单日期的起始和结束时间这几个条件一起查询。
先看分页的,目前spring data jpa给我们做分页的Repository是PagingAndSortingRepository,但它满足不了自定义查询条件,只能另选JpaRepository。那么不分页的Repository呢?其实还是它。接下来看怎么实现:
Repository:
- import com.crocodile.springboot.model.Flow;
- import org.springframework.data.domain.Page;
- import org.springframework.data.domain.Pageable;
- import org.springframework.data.jpa.domain.Specification;
- import org.springframework.data.jpa.repository.JpaRepository;
- import java.util.List;
- public interface FlowRepository extends JpaRepository<Flow, Long> {
- Long count(Specification<Flow> specification);
- Page<Flow> findAll(Specification<Flow> specification, Pageable pageable);
- List<Flow> findAll(Specification<Flow> specification);
- }
Service:
- /**
- * 获取结果集
- *
- * @param status
- * @param pageNo
- * @param pageSize
- * @param userName
- * @param createTimeStart
- * @param createTimeEnd
- * @return
- */
- public List<Flow> queryFlows(int pageNo, int pageSize, String status, String userName, Date createTimeStart, Date createTimeEnd) {
- List<Flow> result = null;
- // 构造自定义查询条件
- Specification<Flow> queryCondition = new Specification<Flow>() {
- @Override
- public Predicate toPredicate(Root<Flow> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
- List<Predicate> predicateList = new ArrayList<>();
- if (userName != null) {
- predicateList.add(criteriaBuilder.equal(root.get("currentOperator"), userName));
- }
- if (status != null) {
- predicateList.add(criteriaBuilder.equal(root.get("status"), status));
- }
- if (createTimeStart != null && createTimeEnd != null) {
- predicateList.add(criteriaBuilder.between(root.get("createTime"), createTimeStart, createTimeEnd));
- }
- return criteriaBuilder.and(predicateList.toArray(new Predicate[predicateList.size()]));
- }
- };
- // 分页和不分页,这里按起始页和每页展示条数为0时默认为不分页,分页的话按创建时间降序
- try {
- if (pageNo == 0 && pageSize == 0) {
- result = flowRepository.findAll(queryCondition);
- } else {
- result = flowRepository.findAll(queryCondition, PageRequest.of(pageNo - 1, pageSize, Sort.by(Sort.Direction.DESC, "createTime"))).getContent();
- }
- } catch (Exception e) {
- LOGGER.error("--queryFlowByCondition-- error : ", e);
- }
- return result;
- }
上面我们可以看到,套路很简单,就是两板斧:先通过Specification对象定义好自定义的多查询条件,我这里的条件是当传了当前用户时,那么将它加入到查询条件中,不传该参数自然就不加,同理,传了订单状态的话那是通过相等来判断,最后,如果传了起始和结束时间,通过between来查在起始和结束之间的数据;第二板斧调用我们在Repository中定义好的findAll方法,如果分页就用带Pageable分页对象参数的方法,不分页不带该参数即可。
如果你的自定义查询条件里需要模糊查询,比如我有个订单ID要支持模糊查询,也很简单:
- if (orderId!= null) {
- predicateList.add(criteriaBuilder.like(root.get("orderId"), "%" + orderId+ "%"));}
最后我们看回到FlowRepository的第一个方法count,它是返回不分页的多查询的总记录数的,套路也是一样的:
- /**
- * 查记录数
- *
- * @param status
- * @param userName
- * @param createTimeStart
- * @param createTimeEnd
- * @return
- */
- public Long getCounts(String status, String userName, Date createTimeStart, Date createTimeEnd) {
- Long total = 0L;
- Specification<Flow> countCondition = new Specification<Flow>() {
- @Override
- public Predicate toPredicate(Root<Flow> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
- List<Predicate> predicateList = new ArrayList<>();
- if (userName != null) {
- predicateList.add(criteriaBuilder.equal(root.get("currentOperator"), userName));
- }
- if (status != null) {
- predicateList.add(criteriaBuilder.equal(root.get("status"), status));
- }
- if (createTimeStart != null && createTimeEnd != null) {
- predicateList.add(criteriaBuilder.between(root.get("createTime"), createTimeStart, createTimeEnd));
- }
- return criteriaBuilder.and(predicateList.toArray(new Predicate[predicateList.size()]));
- }
- };
- try {
- total = flowRepository.count(countCondition);
- } catch (Exception e) {
- LOGGER.error("--getCountsByCondition-- error: ", e);
- }
- return total;
- }
spring data jpa实现多条件查询(分页和不分页)的更多相关文章
- Spring MVC和Spring Data JPA之按条件查询和分页(kkpaper分页组件)
推荐视频:尚硅谷Spring Data JPA视频教程,一学就会,百度一下就有, 后台代码:在DAO层继承Spring Data JPA的PagingAndSortingRepository接口实现的 ...
- Spring Data JPA中的动态查询 时间日期
功能:Spring Data JPA中的动态查询 实现日期查询 页面对应的dto类private String modifiedDate; //实体类 @LastModifiedDate protec ...
- spring data jpa使用原生sql查询
spring data jpa使用原生sql查询 @Repository public interface AjDao extends JpaRepository<Aj,String> { ...
- Spring Data JPA 复杂/多条件组合查询
1: 编写DAO类或接口 dao类/接口 需继承 public interface JpaSpecificationExecutor<T> 接口: 如果需要分页,还可继承 public ...
- Spring data jpa 实现简单动态查询的通用Specification方法
本篇前提: SpringBoot中使用Spring Data Jpa 实现简单的动态查询的两种方法 这篇文章中的第二种方法 实现Specification 这块的方法 只适用于一个对象针对某一个固定字 ...
- Spring Data Jpa (四)注解式查询方法
详细讲解声明式的查询方法 1 @Query详解 使用命名查询为实体声明查询是一种有效的方法,对于少量查询很有效.一般只需要关心@Query里面的value和nativeQuery的值.使用声明式JPQ ...
- Spring Data JPA 自定义对象接收查询结果集
Spring Data JPA 简介 Spring Data JPA 是 Spring 基于 ORM 框架.JPA 规范的基础上封装的一套JPA应用框架,可使开发者用极简的代码即可实现对数据库的访问和 ...
- Spring Data JPA 的 Specifications动态查询
主要的结构: 有时我们在查询某个实体的时候,给定的条件是不固定的,这时就需要动态构建相应的查询语句,在Spring Data JPA中可以通过JpaSpecificationExecutor接口查询. ...
- Spring Data Jpa的四种查询方式
一.调用接口的方式 1.基本介绍 通过调用接口里的方法查询,需要我们自定义的接口继承Spring Data Jpa规定的接口 public interface UserDao extends JpaR ...
随机推荐
- KVM虚拟机高级设置——08 管理远程虚拟机
在搭建KVM环境——07 带GUI的Linux上安装KVM图形界面管理工具介绍了KVM图形化管理工具,这款工具除了可以管理本地KVM虚拟外,还可以管理远程KVM虚拟机. 输入113机器密码 输入yes ...
- duilib学习领悟(2)
再次强调,duilib只不过是一种思想! 在上一节中,我剖析了duilib中窗口类的注册,其中遗留两个小问题没有细说的? 第一个问题:过程函数中__WndProc()中有这么一小段代码: pThis ...
- Cannot modify resource set without a write transaction 问题
TransactionalEditingDomainImpl editingDomain = (TransactionalEditingDomainImpl) diagramEditor.getEdi ...
- android studio调试报错:java.lang.RuntimeException: Unable to start activity ComponentInfo
报错信息: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.pro_u_loc/com.e ...
- harbor1.9.0 仓库的搭建
配置及文中的xxx 为你自己的配置信息 1.创建目录 mkdir -p /data/soft cd /data/soft 2.安装docker-composer 2.1官方安装 c ...
- python自动华 (十四)
Python自动化 [第十四篇]:HTML介绍 本节内容: Html 概述 HTML文档 常用标签 2. CSS 概述 CSS选择器 CSS常用属性 1.HTML 1.1概述 HTML是英文Hyper ...
- TFS命令行
tfs命令工具: https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/9s5ae285 ...
- Invalid HTTP_HOST header: 'xxx.xxx:8000'. You may need to add 'xxx.xx' to ALLOWED_HOSTS
用python3 manage.py runserver 0.0.0.0:8000命令运行django程序后,通过浏览器访问服务器网址的8000端口,出现访问错误,报错为 Invalid HTTP_H ...
- ckeditor不能粘贴word的问题
在之前在工作中遇到在富文本编辑器中粘贴图片不能展示的问题,于是各种网上扒拉,终于找到解决方案,在这里感谢一下知乎中众大神以及TheViper. 通过知乎提供的思路找到粘贴的原理,通过TheViper找 ...
- ie8 ajax 跨域问题
最近做了个客服端要通过ocx获得初始化数据就是一个html页面镶嵌在一个c++做的程序里面通过c++做的程序的一个按钮来打开我的这个html页面但是页面中的ajax就是用不了又不报错 后来加入了cro ...