目前的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实现多条件查询(分页和不分页)的更多相关文章

  1. Spring MVC和Spring Data JPA之按条件查询和分页(kkpaper分页组件)

    推荐视频:尚硅谷Spring Data JPA视频教程,一学就会,百度一下就有, 后台代码:在DAO层继承Spring Data JPA的PagingAndSortingRepository接口实现的 ...

  2. Spring Data JPA中的动态查询 时间日期

    功能:Spring Data JPA中的动态查询 实现日期查询 页面对应的dto类private String modifiedDate; //实体类 @LastModifiedDate protec ...

  3. spring data jpa使用原生sql查询

    spring data jpa使用原生sql查询 @Repository public interface AjDao extends JpaRepository<Aj,String> { ...

  4. Spring Data JPA 复杂/多条件组合查询

    1: 编写DAO类或接口  dao类/接口 需继承 public interface JpaSpecificationExecutor<T> 接口: 如果需要分页,还可继承 public ...

  5. Spring data jpa 实现简单动态查询的通用Specification方法

    本篇前提: SpringBoot中使用Spring Data Jpa 实现简单的动态查询的两种方法 这篇文章中的第二种方法 实现Specification 这块的方法 只适用于一个对象针对某一个固定字 ...

  6. Spring Data Jpa (四)注解式查询方法

    详细讲解声明式的查询方法 1 @Query详解 使用命名查询为实体声明查询是一种有效的方法,对于少量查询很有效.一般只需要关心@Query里面的value和nativeQuery的值.使用声明式JPQ ...

  7. Spring Data JPA 自定义对象接收查询结果集

    Spring Data JPA 简介 Spring Data JPA 是 Spring 基于 ORM 框架.JPA 规范的基础上封装的一套JPA应用框架,可使开发者用极简的代码即可实现对数据库的访问和 ...

  8. Spring Data JPA 的 Specifications动态查询

    主要的结构: 有时我们在查询某个实体的时候,给定的条件是不固定的,这时就需要动态构建相应的查询语句,在Spring Data JPA中可以通过JpaSpecificationExecutor接口查询. ...

  9. Spring Data Jpa的四种查询方式

    一.调用接口的方式 1.基本介绍 通过调用接口里的方法查询,需要我们自定义的接口继承Spring Data Jpa规定的接口 public interface UserDao extends JpaR ...

随机推荐

  1. golang的序列化与反序列化的几种方式

    golang用来序列化的模块有很多,我们来介绍3个. json 首先登场的是json,这个几乎毋庸置疑. 序列化 package main import ( "encoding/json&q ...

  2. C++——数组形参退化为指针

    数组做形参退化为指针 如果数组作为函数参数,则数组形参会退化为指针,以下代码在编译器看来是等价的 ]); ]); void fun3(int a[]); void fun4(int *a); #inc ...

  3. 08_Azkaban案例实践1_Command单一job示例

    1.Azkaban实战 Azkaba内置的任务类型支持command.java 2.Command类型单一job示例 1.创建job描述文件:vi command.job #command.job t ...

  4. No package libmcrypt available.

    Centos安装PHP时,安装php依赖包时yum install libmcrypt libmcrypt-devel,报错如下: No package libmcrypt available. No ...

  5. mxnet在windows使用gpu 出错

    1. cuda windows安装 官网下载 代码: import mxnet as mxfrom mxnet import ndfrom mxnet.gluon import nn a = nd.a ...

  6. OpenCV VideoCapture.get()参数详解

    转自https://blog.csdn.net/u011436429/article/details/80604590 方便查阅

  7. Anaconda配置Python开发环境

    Anaconda介绍 Anaconda 是在 linux.windows 和 mac os x 上执行 Python/R 数据分析和机器学习的最简单的方式并且它是开源的.它在全球拥有超过 1, 100 ...

  8. 【转】Golang汇编命令解读

    原文: https://www.cnblogs.com/yjf512/p/6132868.html ------------------------------------------------- ...

  9. Http协议与TCP协议

    背景 在日常工作中,经常会遇到某某框架是基于Http协议或者TCP协议,今天,就针对于该协议,整理下 从本质上来说,Http协议与TCP协议是应用在不同网络层,Http协议处于应用层,TCP处于传输层 ...

  10. java中的文件上传下载

    java中文件上传下载原理 学习内容 文件上传下载原理 底层代码实现文件上传下载 SmartUpload组件 Struts2实现文件上传下载 富文本编辑器文件上传下载 扩展及延伸 学习本门课程需要掌握 ...