目录

一、

二、工具类

1、AbstractSpecification(抽象动态查询条件)

2、各属性查询条件(IsNull、In、Number、String、Like等)

(1)字符串属性查询条件StringSpecification

(2)、Between动态查询条件BetweenSpecification

(3)相等动态查询条件EqualSpecification

(4)In动态查询条件InSpecification

(5)判空查询条件IsNullSpecification

(6)Like动态查询条件LikeSpecification

(7)不为空动态查询条件NotNullSpecification

(8)数字属性查询条件NumberSpecification

(9)SpecificationGroup

(10)SpecificationHelper

(11)分组查询

(12)2019-06-17补充 or 用法

三、用法


适用于多条件动态查询的业务场景。

刚毕业技术比较差,所以记录的比较详细。

一、

repository继承JpaSpecificationExecutor<VehEntity>

public interface VehRepository extends JpaRepository<VehEntity, String>, JpaSpecificationExecutor<VehEntity>
{
}

二、工具类

1、AbstractSpecification(抽象动态查询条件)

import org.springframework.data.jpa.domain.Specification;/*** 抽象动态查询条件**/
public abstract class AbstractSpecification<T, ATTR> implements Specification<T>
{/*** 逻辑运算:等于*/public static final int LOGICAL_OPERATOR_EQUAL = 1;/*** 逻辑运算:小于*/public static final int LOGICAL_OPERATOR_LESS = 2;/*** 逻辑运算:大于*/public static final int LOGICAL_OPERATOR_GREATER = 3;/*** 逻辑运算:小于等于*/public static final int LOGICAL_OPERATOR_LESS_EQUAL = 4;/*** 逻辑运算:大于等于*/public static final int LOGICAL_OPERATOR_GREATER_EQUAL = 5;/*** 逻辑运算:不等于*/public static final int LOGICAL_OPERATOR_NOT_EQUAL = 6;/*** 逻辑运算:包含*/public static final int LOGICAL_OPERATOR_LIKE = 7;/*** 逻辑运算:左包含*/public static final int LOGICAL_OPERATOR_STARTWITH = 8;/*** 逻辑运算:右包含*/public static final int LOGICAL_OPERATOR_ENDWITH = 9;/*** 逻辑运算:非空*/public static final int LOGICAL_OPERATOR_NOT_NULL = 10;/*** 逻辑运算:In*/public static final int LOGICAL_OPERATOR_IN = 11;/*** 逻辑运算:包含(自定义)*/public static final int LOGICAL_OPERATOR_LIKE_CUSTOM = 99;public static final int LOGICAL_OPERATOR_CUSTOM = 100;protected String attrName;protected ATTR attrValue;protected ATTR[] attrValues;protected int logicalOperator;/*** 构造方法* @param attrName          属性名称* @param attrValue         属性值* @param logicalOperator    逻辑运算符*/public AbstractSpecification(String attrName, ATTR attrValue, int logicalOperator) {super();this.attrName = attrName;this.attrValue = attrValue;this.logicalOperator = logicalOperator;}public AbstractSpecification(String attrName, int logicalOperator, ATTR ... attrValues) {super();this.attrName = attrName;this.attrValues = attrValues;if (this.attrValues.length > 0) {this.attrValue = this.attrValues[0];}this.logicalOperator = logicalOperator;}
}

2、各属性查询条件(IsNull、In、Number、String、Like等)

(1)字符串属性查询条件StringSpecification

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import javax.persistence.criteria.*;/*** 字符串属性查询条件*/
public class StringSpecification<T> extends AbstractSpecification<T, String> {private static Logger log = LoggerFactory.getLogger(StringSpecification.class);private int start, len;/*** 构造方法** @param attrName        属性名称* @param attrValue       属性值* @param logicalOperator 逻辑运算符*/public StringSpecification(String attrName, String attrValue, int logicalOperator) {this(attrName, logicalOperator, attrValue);}public StringSpecification(String attrName, int logicalOperator, String... attrValues) {super(attrName, logicalOperator, attrValues);this.start = 0;this.len = 0;}public StringSpecification(String attrName, int start, int length, int logicalOperator, String... attrValues) {super(attrName, logicalOperator, attrValues);this.start = start;this.len = length;}private Class<?> getFieldClass(String attr) {// TODOreturn null;}/* (non-Javadoc)* @see org.springframework.data.jpa.domain.Specification#toPredicate(javax.persistence.criteria.Root, javax.persistence.criteria.CriteriaQuery, javax.persistence.criteria.CriteriaBuilder)*/@Overridepublic Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {Path<String> path = SpecificationHelper.getPath(root, attrName);Expression<String> expr = path;if (0 < start && 0 < len) {expr = cb.substring(path, start, len);} else {}switch (logicalOperator) {case StringSpecification.LOGICAL_OPERATOR_EQUAL: {return cb.equal(expr, attrValue);}case StringSpecification.LOGICAL_OPERATOR_GREATER: {return cb.greaterThan(expr, attrValue);}case StringSpecification.LOGICAL_OPERATOR_GREATER_EQUAL: {return cb.greaterThanOrEqualTo(expr, attrValue);}case StringSpecification.LOGICAL_OPERATOR_LESS: {return cb.lessThan(expr, attrValue);}case StringSpecification.LOGICAL_OPERATOR_LESS_EQUAL: {return cb.lessThanOrEqualTo(expr, attrValue);}case StringSpecification.LOGICAL_OPERATOR_NOT_EQUAL: {return cb.notEqual(expr, attrValue);}case StringSpecification.LOGICAL_OPERATOR_LIKE: {return cb.like(expr, "%" + attrValue + "%");}case StringSpecification.LOGICAL_OPERATOR_STARTWITH: {return cb.like(expr, attrValue + "%");}case StringSpecification.LOGICAL_OPERATOR_ENDWITH: {return cb.like(expr, "%" + attrValue);}case StringSpecification.LOGICAL_OPERATOR_NOT_NULL: {return cb.isNotNull(path);}case StringSpecification.LOGICAL_OPERATOR_LIKE_CUSTOM: {return cb.like(expr, attrValue);}case StringSpecification.LOGICAL_OPERATOR_IN: {CriteriaBuilder.In<String> predicate = cb.in(expr);for (String item : attrValues) {predicate.value(item);}return predicate;}default:return null;}}
}

(2)、Between动态查询条件BetweenSpecification

import org.springframework.data.jpa.domain.Specification;import javax.persistence.criteria.*;/*** Between动态查询条件*/
public class BetweenSpecification<T, ATTR extends Comparable<ATTR>> implements Specification<T>
{private String attrName;private ATTR lowerBound, upperBound;/*** 构造方法* @param attrName        属性名称* @param lowerBound    属性值下界* @param upperBound   属性值上界*/public BetweenSpecification(String attrName, ATTR lowerBound, ATTR upperBound) {super();this.attrName = attrName;this.lowerBound = lowerBound;this.upperBound = upperBound;}/* (non-Javadoc)* @see org.springframework.data.jpa.domain.Specification#toPredicate(javax.persistence.criteria.Root, javax.persistence.criteria.CriteriaQuery, javax.persistence.criteria.CriteriaBuilder)*/@Overridepublic Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {Path<ATTR> path = SpecificationHelper.getPath(root, attrName);return cb.between(path, lowerBound, upperBound);}}

(3)相等动态查询条件EqualSpecification

import org.springframework.data.jpa.domain.Specification;import javax.persistence.criteria.*;/*** 相等动态查询条件**/
public class EqualSpecification<T, ATTR> implements Specification<T>
{private String fieldName;private ATTR fieldValue;public EqualSpecification(String fieldName, ATTR fieldValue) {super();this.fieldName = fieldName;this.fieldValue = fieldValue;}@Overridepublic Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {Path<ATTR> path = SpecificationHelper.getPath(root, fieldName);return cb.equal(path, fieldValue);}}

(4)In动态查询条件InSpecification

import org.springframework.data.jpa.domain.Specification;import javax.persistence.criteria.*;/****/
public class InSpecification<T, ATTR> implements Specification<T>
{private String attrName;private ATTR[] values;public InSpecification(String attrName, ATTR[] values) {this.attrName = attrName;this.values = values;}@Overridepublic Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {Path<ATTR> path = SpecificationHelper.getPath(root, attrName);CriteriaBuilder.In<ATTR> predicate = cb.in(path);for(ATTR item : values) {predicate.value(item);}return predicate;}
}

(5)判空查询条件IsNullSpecification

import javax.persistence.criteria.*;/*** */
public class IsNullSpecification<T> extends AbstractSpecification<T,Object> {public IsNullSpecification(String attrName) {super(attrName, null, AbstractSpecification.LOGICAL_OPERATOR_CUSTOM);}@Overridepublic Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {Path<Object> path = SpecificationHelper.getPath(root, attrName);return cb.isNull(path);}
}

(6)Like动态查询条件LikeSpecification

/*** Like动态查询条件**/
public class LikeSpecification<T> extends StringSpecification<T> {public LikeSpecification(String attrName, String attrValue) {super(attrName, attrValue, StringSpecification.LOGICAL_OPERATOR_LIKE);}}

(7)不为空动态查询条件NotNullSpecification

import javax.persistence.criteria.*;/*** */
public class NotNullSpecification<T> extends AbstractSpecification<T,Object> {public NotNullSpecification(String attrName) {super(attrName, null, AbstractSpecification.LOGICAL_OPERATOR_CUSTOM);}@Overridepublic Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {Path<Object> path = SpecificationHelper.getPath(root, attrName);return cb.isNotNull(path);}
}

(8)数字属性查询条件NumberSpecification

import javax.persistence.criteria.*;/*** 数字属性查询条件*/
public class NumberSpecification<T> extends AbstractSpecification<T, Number> {public NumberSpecification(String attrName, Number attrValue, int logicalOperator) {this(attrName, logicalOperator, attrValue);}public NumberSpecification(String attrName, int logicalOperator, Number... attrValues) {super(attrName, logicalOperator, attrValues);}@Overridepublic Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {Path<Number> path = SpecificationHelper.getPath(root, attrName);switch (logicalOperator) {case NumberSpecification.LOGICAL_OPERATOR_EQUAL: {return cb.equal(path, attrValue);}case NumberSpecification.LOGICAL_OPERATOR_GREATER: {return cb.gt(path, attrValue);}case NumberSpecification.LOGICAL_OPERATOR_GREATER_EQUAL: {return cb.ge(path, attrValue);}case NumberSpecification.LOGICAL_OPERATOR_LESS: {return cb.lt(path, attrValue);}case NumberSpecification.LOGICAL_OPERATOR_LESS_EQUAL: {return cb.le(path, attrValue);}case NumberSpecification.LOGICAL_OPERATOR_NOT_EQUAL: {return cb.notEqual(path, attrValue);}case NumberSpecification.LOGICAL_OPERATOR_IN: {CriteriaBuilder.In<Number> predicate = cb.in(path);for (Number item : attrValues) {predicate.value(item);}return predicate;}default:return null;}}}

(9)SpecificationGroup

import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.domain.Specifications;import java.util.List;/****/
public class SpecificationGroup {public static <T> Specifications<T> and(List<Specification<T>> specList) {Specifications<T> specs = null;for(Specification<T> s : specList) {if(specs != null) {specs = specs.and(s);} else {specs = Specifications.where(s);}}return specs;}public static <T> Specifications<T> or(List<Specification<T>> specList) {Specifications<T> specs = null;for(Specification<T> s : specList) {if(specs != null) {specs = specs.or(s);} else {specs = Specifications.where(s);}}return specs;}
}

(10)SpecificationHelper

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.domain.Specifications;import javax.persistence.criteria.From;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Root;
import java.util.List;
import java.util.StringTokenizer;/****/
public class SpecificationHelper {private static Logger log = LoggerFactory.getLogger(SpecificationHelper.class);public static <ATTR, E> Path<ATTR> getPath(Root<E> root, String attrName) {From<E, ?> f = root;String[] strs = attrName.split("\\.");String attr = attrName;if (strs.length > 1) {for(int i = 0; i < strs.length; i ++) {attr = strs[i];if(i < strs.length - 1) {boolean hasAttribute = false;if (root.getJoins() != null) {for (Join<E, ?> join : root.getJoins()) {if (attr.equals(join.getAttribute().getName())) {f = join;hasAttribute = true;break;}}}if(!hasAttribute) {f = f.join(attr);}}}}return f.get(attr);}public static <E> From<E, ?> fromCollection(Root<E> root, String attrName) {From<E, ?> f = root;String attr = attrName;StringTokenizer tokenizer = new StringTokenizer(attrName, ".");while (tokenizer.hasMoreTokens()) {attr = tokenizer.nextToken();boolean hasAttribute = false;if (root.getJoins() != null) {for (Join<E, ?> join : root.getJoins()) {if (attr.equals(join.getAttribute().getName())) {f = join;hasAttribute = true;break;}}}if(!hasAttribute) {f = f.join(attr);}}return f;}public static <T> Specifications<T> and(List<Specification<T>> specList) {return SpecificationGroup.and(specList);}public static <T> Specifications<T> or(List<Specification<T>> specList) {return SpecificationGroup.or(specList);}}

(11)分组查询

2019.02.19更新


public class GroupSpecification implements Specification<T> {@Overridepublic Specification<T> and(Specification<T> other) {return null;}@Overridepublic Specification<T> or(Specification<T> other) {return null;}@SuppressWarnings("unchecked")@Overridepublic Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb){@SuppressWarnings("rawtypes") List eList=new ArrayList<>();eList.add(root.<String>get("detectSn"));query.groupBy(eList);
//        query.having(cb.gt( cb.count(root), 1));return query.getRestriction();}
}

(12)2019-06-17补充 or 用法

List<Specification<VehWarnEntrty>> list = new ArrayList<>();List<Specification<VehWarnEntrty>> list2 = new ArrayList<>();//需要做OR操作的字段
list2.add(new EqualSpecification<VehWarnEntrty,String>("ifOutRange","true"));
list2.add(new EqualSpecification<VehWarnEntrty,String>("ifIllegal","true"));
list2.add(new EqualSpecification<VehWarnEntrty,String>("ifHighSpeed","true"));
//添加OR操作的list
list.add(SpecificationHelper.or(list2));

三、用法

创建list

List<Specification<VehEntity>> list = new ArrayList<>();

向list中添加条件

(下面代码的意思是 字符串属性 vehNo这个字段 右包含某个值)

list.add(new StringSpecification<>("vehNo", StringTool.trim(vehQueryParam.getVehNo()), StringSpecification.LOGICAL_OPERATOR_ENDWITH));

(下面代码的意思是 In 代码中detectResult字段 中含有(in)detectResult数组中的值 则取出来)

        String [] detectResult = new String[5];detectResult[0]="合格";detectResult[1]="不合格";detectResult[2]="一级";detectResult[3]="二级";detectResult[4]="三级";list.add(new InSpecification<>("detectResult",detectResult));

其他的几个用法就不一一举例说明...

然后是分页查询

//三个参数 1、页码2、取几个值3、排序方式
PageRequest pageRequest = new PageRequest(detectRecordQueryParam.getPageNum() - 1,detectRecordQueryParam.getPageSize(), new Sort(new Order(Direction.DESC, "detectDate")));Page<VehicleEntity> page;if (list.isEmpty()) {page = vehRepository.findAll(pageRequest);} else {
//前端查询条件传过来的参数 不为空  就是说要用户进行条件查询了 就将list动态查询条件给他page = vehRepository.findAll(SpecificationHelper.and(list), pageRequest);}

结果操作

使用PageInfo存储查询结果

(这是PageInfo)

import java.util.ArrayList;
import java.util.List;/***/
public class PageInfo<T> extends PageBase
{private List<T> records = new ArrayList<T>();public List<T> getRecords() {return records;}public void setRecords(List<T> records) {this.records = records;}
}

PageInfo使用

//对应的Info而不是entity
PageInfo<VehInfo> result = new PageInfo<VehListItem>();result.setTotalPages(page.getTotalPages());result.setPageNo(page.getNumber());result.setPageSize(page.getSize());result.setTotalRecords(page.getTotalElements());

对象转换重构

for (VehEntity entity : page.getContent()) {VehListItem item = new VehicleListItem();// 对象转换重构item.setVehicleId(entity.getVehicleId());item.setVehicleNo(entity.getVehicleNo());result.getRecords().add(item);}

这里的result 就是要返回给前端的 结果集

spring data jpa 动态查询Specification(包括各个In、like、Between等等各种工具类,及完整(分页查询)用法步骤(到返回给前端的结果))相关推荐

  1. 对Spring Data JPA中的page对象下的content属性里的实体类对象转换为dto对象

    对Spring Data JPA中的page对象下的content属性里的实体类对象转换为dto对象. 刚开始试遍历content,进行转换,添加到新的list中,再set进去page.后来发现pag ...

  2. Spring data jpa 动态查询封装

    最近几天学习一下jpa,发现在动态查询方面支持不是很好,一个包含多种动态查询条件的列表需要写大量的代码,而我本身有强迫症,代码有洁癖,大量的重复的代码,自然不爽,于是就.......,废话少说,直接上 ...

  3. Spring Data JPA 动态拼接条件的通用设计模式

    记住官方文档永远是首选 import java.sql.Timestamp; import java.util.ArrayList; import java.util.List; import jav ...

  4. spring data jpa封装specification实现简单风格的动态查询

    github:https://github.com/peterowang/spring-data-jpa-demo 单一实体的动态查询: @Servicepublic class AdvancedUs ...

  5. Spring Boot的Spring Data JPA示例

    1.简介 在本文中,我们将演示如何利用功能强大的Spring Data JPA API与本课程中的数据库(内存中的H2数据库)进行交互. Spring Data JPA提供了一组非常强大且高度抽象的接 ...

  6. ORM框架之Spring Data JPA(二)spring data jpa方式的基础增删改查

    上一篇主要在介绍hibernate实现jpa规范,如何实现数据增删改查,这一篇将会着重spring data jpa 一.Spring Data JPA 1.1 Spring Data JPA介绍: ...

  7. Spring Data JPA 自定义Repository接口与子接口

    上篇文章介绍了 Repository接口的使用(Spring Data JPA介绍与Spring的整合),接下来重点掌握 Repository的CrudRepository子接口下的子接口. 在dao ...

  8. Spring Data JPA - 参考文档-3

    参考文档 4. JPA存储库 本章将指出JPA对知识库的支持.这建立在使用Spring Data Repositories中解释的核心存储库支持上.所以要确保你对这里解释的基本概念有一个很好的理解. ...

  9. 第九章SpringBoot整合Spring Data JPA

    目录 1 概述 2 Spring Data JPA整合 2.1 pom文件 2.2 配置文件 2.3 实体类 2.4 Dao接口 2.5 启动类 2.6 编写测试类 3 Spring Data JPA ...

  10. 【Spring Data JPA自学笔记二】初识Spring Data JPA

    文章目录 Spring Data JPA是什么? Spring Data JPA的配置 配置pom.xml 配置applicationContext.xml Spring Data JPA的使用 Sp ...

最新文章

  1. IOS时间传递机制简记
  2. cad绘制椭圆的方法有几种_CAD新手入门教学:如何绘制矩形?
  3. 线上服务CPU100%问题快速定位实战(转载公众号:架构师之路)
  4. html格式文档结构保存数据库6,freeCAD文档结构
  5. wangeditor修改图片上传和视频上传
  6. 外设驱动库开发笔记25:FM25xxx FRAM存储器驱动
  7. axios php文件登录,JWT实战:使用axios+PHP实现登录认证
  8. mysql分区表优缺点,Mysql 表分区和性能
  9. Web服务器与Servlet容器初步认识
  10. 30 年间,软件开发行业为何 Bug 纷飞?
  11. R语言入门mac——RStudio安装➕R包安装【附安装链接】
  12. h3c防火墙服务器ip修改,H3C防火墙常用配置命令
  13. 经纬财富:亳州炒白银操作方法,谨防亏损
  14. 2017年PHP程序员未来路在何方——韩天峰
  15. 响应式编程之一:概述
  16. python和excel相关的是什么知识点_Python 与 Excel 不得不说的事
  17. stm32f103开发板入门到手进行开发
  18. 手机变速齿轮_变速齿轮神途官方版下载-变速齿轮神途手游官方版下载 v2.20190828-114手机乐园...
  19. 虚幻4学习日志2021.3.29 为这个ACT游戏结个尾
  20. Crypto++编译使用

热门文章

  1. 介绍-Linux capability机制
  2. ARM base instruction -- orr
  3. windows WTS 服务与桌面交互
  4. HBuilder(H5+App)中集成腾讯云通信IM功能
  5. 手把手教你用UNet做医学图像分割系统
  6. NPOI Word 换行 【XWPFDocument】
  7. PHP 开发杂谈:对后端开发的思考
  8. android获取连接wifi名称,Android开发:获取手机当前连接的WiFi名称
  9. php 手机版 答题系统,基于ThinkPHP框架开发的驾考在线答题系统_WAP手机自适应界面+手机在线驾考宝典答题系统...
  10. 10-Little prince's trip to Java-奇数魔方阵