spring data jpa 动态查询Specification(包括各个In、like、Between等等各种工具类,及完整(分页查询)用法步骤(到返回给前端的结果))
目录
一、
二、工具类
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等等各种工具类,及完整(分页查询)用法步骤(到返回给前端的结果))相关推荐
- 对Spring Data JPA中的page对象下的content属性里的实体类对象转换为dto对象
对Spring Data JPA中的page对象下的content属性里的实体类对象转换为dto对象. 刚开始试遍历content,进行转换,添加到新的list中,再set进去page.后来发现pag ...
- Spring data jpa 动态查询封装
最近几天学习一下jpa,发现在动态查询方面支持不是很好,一个包含多种动态查询条件的列表需要写大量的代码,而我本身有强迫症,代码有洁癖,大量的重复的代码,自然不爽,于是就.......,废话少说,直接上 ...
- Spring Data JPA 动态拼接条件的通用设计模式
记住官方文档永远是首选 import java.sql.Timestamp; import java.util.ArrayList; import java.util.List; import jav ...
- spring data jpa封装specification实现简单风格的动态查询
github:https://github.com/peterowang/spring-data-jpa-demo 单一实体的动态查询: @Servicepublic class AdvancedUs ...
- Spring Boot的Spring Data JPA示例
1.简介 在本文中,我们将演示如何利用功能强大的Spring Data JPA API与本课程中的数据库(内存中的H2数据库)进行交互. Spring Data JPA提供了一组非常强大且高度抽象的接 ...
- ORM框架之Spring Data JPA(二)spring data jpa方式的基础增删改查
上一篇主要在介绍hibernate实现jpa规范,如何实现数据增删改查,这一篇将会着重spring data jpa 一.Spring Data JPA 1.1 Spring Data JPA介绍: ...
- Spring Data JPA 自定义Repository接口与子接口
上篇文章介绍了 Repository接口的使用(Spring Data JPA介绍与Spring的整合),接下来重点掌握 Repository的CrudRepository子接口下的子接口. 在dao ...
- Spring Data JPA - 参考文档-3
参考文档 4. JPA存储库 本章将指出JPA对知识库的支持.这建立在使用Spring Data Repositories中解释的核心存储库支持上.所以要确保你对这里解释的基本概念有一个很好的理解. ...
- 第九章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 ...
- 【Spring Data JPA自学笔记二】初识Spring Data JPA
文章目录 Spring Data JPA是什么? Spring Data JPA的配置 配置pom.xml 配置applicationContext.xml Spring Data JPA的使用 Sp ...
最新文章
- IOS时间传递机制简记
- cad绘制椭圆的方法有几种_CAD新手入门教学:如何绘制矩形?
- 线上服务CPU100%问题快速定位实战(转载公众号:架构师之路)
- html格式文档结构保存数据库6,freeCAD文档结构
- wangeditor修改图片上传和视频上传
- 外设驱动库开发笔记25:FM25xxx FRAM存储器驱动
- axios php文件登录,JWT实战:使用axios+PHP实现登录认证
- mysql分区表优缺点,Mysql 表分区和性能
- Web服务器与Servlet容器初步认识
- 30 年间,软件开发行业为何 Bug 纷飞?
- R语言入门mac——RStudio安装➕R包安装【附安装链接】
- h3c防火墙服务器ip修改,H3C防火墙常用配置命令
- 经纬财富:亳州炒白银操作方法,谨防亏损
- 2017年PHP程序员未来路在何方——韩天峰
- 响应式编程之一:概述
- python和excel相关的是什么知识点_Python 与 Excel 不得不说的事
- stm32f103开发板入门到手进行开发
- 手机变速齿轮_变速齿轮神途官方版下载-变速齿轮神途手游官方版下载 v2.20190828-114手机乐园...
- 虚幻4学习日志2021.3.29 为这个ACT游戏结个尾
- Crypto++编译使用
热门文章
- 介绍-Linux capability机制
- ARM base instruction -- orr
- windows WTS 服务与桌面交互
- HBuilder(H5+App)中集成腾讯云通信IM功能
- 手把手教你用UNet做医学图像分割系统
- NPOI Word 换行 【XWPFDocument】
- PHP 开发杂谈:对后端开发的思考
- android获取连接wifi名称,Android开发:获取手机当前连接的WiFi名称
- php 手机版 答题系统,基于ThinkPHP框架开发的驾考在线答题系统_WAP手机自适应界面+手机在线驾考宝典答题系统...
- 10-Little prince's trip to Java-奇数魔方阵