Spring Data JPA支持JPA2.0的Criteria查询,相应的接口是JpaSpecificationExecutor。Criteria 查询:是一种类型安全和更面向对象的查询 。

这个接口基本是围绕着Specification接口来定义的, Specification接口中只定义了如下一个方法:

Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);

要理解这个方法,以及正确的使用它,就需要对JPA2.0的Criteria查询有一个足够的熟悉和理解,因为这个方法的参数和返回值都是JPA标准里面定义的对象。

Criteria查询基本概念

Criteria 查询是以元模型的概念为基础的,元模型是为具体持久化单元的受管实体定义的,这些实体可以是实体类,嵌入类或者映射的父类。

CriteriaQuery接口:代表一个specific的顶层查询对象,它包含着查询的各个部分,比如:select 、from、where、group by、order by等注意:CriteriaQuery对象只对实体类型或嵌入式类型的Criteria查询起作用 
Root接口:代表Criteria查询的根对象,Criteria查询的查询根定义了实体类型,能为将来导航获得想要的结果,它与SQL查询中的FROM子句类似

1:Root实例是类型化的,且定义了查询的FROM子句中能够出现的类型。

2:查询根实例能通过传入一个实体类型给 AbstractQuery.from方法获得。

3:Criteria查询,可以有多个查询根。

4:AbstractQuery是CriteriaQuery 接口的父类,它提供得到查询根的方法。CriteriaBuilder接口:用来构建CritiaQuery的构建器对象Predicate:一个简单或复杂的谓词类型,其实就相当于条件或者是条件组合。

Criteria查询基本对象的构建

1:通过EntityManager的getCriteriaBuilder或EntityManagerFactory的getCriteriaBuilder方法可以得到CriteriaBuilder对象2:通过调用CriteriaBuilder的createQuery或createTupleQuery方法可以获得CriteriaQuery的实例

3:通过调用CriteriaQuery的from方法可以获得Root实例过滤条件

A:过滤条件会被应用到SQL语句的FROM子句中。在criteria 查询中,查询条件通过Predicate或Expression实例应用到CriteriaQuery对象上。B:这些条件使用 CriteriaQuery .where 方法应用到CriteriaQuery 对象上C:CriteriaBuilder也作为Predicate实例的工厂,通过调用CriteriaBuilder 的条件
方( equalnotEqual, gt, ge,lt, le,between,like等)创建Predicate对象。D:复合的Predicate 语句可以使用CriteriaBuilder的and, or andnot 方法构建。 构建简单的Predicate示例:
            Predicate p1=cb.like(root.get(“name”).as(String.class), “%”+uqm.getName()+“%”);Predicate p2=cb.equal(root.get("uuid").as(Integer.class), uqm.getUuid());Predicate p3=cb.gt(root.get("age").as(Integer.class), uqm.getAge());构建组合的Predicate示例:Predicate p = cb.and(p3,cb.or(p1,p2));

下面我们用两个示例代码来更深入的了解:

1.复杂条件多表查询
//需要查询的对象
public class Qfjbxxdz {@Id@GeneratedValue(generator = "system-uuid")@GenericGenerator(name = "system-uuid", strategy = "uuid.hex")private String id;@OneToOne@JoinColumn(name = "qfjbxx")private Qfjbxx qfjbxx; //关联表private String fzcc;private String fzccName;@ManyToOne@JoinColumn(name = "criminalInfo")private CriminalInfo criminalInfo;//关联表@Column(length=800)private String bz;//get/set......
}//创建构造Specification的方法
//这里我传入两个条件参数因为与前段框架有关,你们写的时候具体自己业务自行决断
private Specification<Qfjbxxdz> getWhereClause(final JSONArray condetion,final JSONArray search) {return new Specification<Qfjbxxdz>() {@Overridepublic Predicate toPredicate(Root<Qfjbxxdz> root, CriteriaQuery<?> query, CriteriaBuilder cb) {List<Predicate> predicate = new ArrayList<>();Iterator<JSONObject> iterator = condetion.iterator();Predicate preP = null;while(iterator.hasNext()){JSONObject jsonObject = iterator.next();//注意:这里用的root.join 因为我们要用qfjbxx对象里的字段作为条件就必须这样做join方法有很多重载,使用的时候可以多根据自己业务决断Predicate p1 = cb.equal(root.join("qfjbxx").get("id").as(String.class),jsonObject.get("fzId").toString());Predicate p2 = cb.equal(root.get("fzcc").as(String.class),jsonObject.get("ccId").toString());if(preP!=null){preP = cb.or(preP,cb.and(p1,p2));}else{preP = cb.and(p1,p2);}}JSONObject jsonSearch=(JSONObject) search.get(0);Predicate p3=null;if(null!=jsonSearch.get("xm")&&jsonSearch.get("xm").toString().length()>0){p3=cb.like(root.join("criminalInfo").get("xm").as(String.class),"%"+jsonSearch.get("xm").toString()+"%");}Predicate p4=null;if(null!=jsonSearch.get("fzmc")&&jsonSearch.get("fzmc").toString().length()>0){p4=cb.like(root.join("qfjbxx").get("fzmc").as(String.class),"%"+jsonSearch.get("fzmc").toString()+"%");}Predicate preA;if(null!=p3&&null!=p4){Predicate  preS =cb.and(p3,p4);preA =cb.and(preP,preS);}else if(null==p3&&null!=p4){preA=cb.and(preP,p4);}else if(null!=p3&&null==p4){preA=cb.and(preP,p3);}else{preA=preP;}predicate.add(preA);Predicate[] pre = new Predicate[predicate.size()];query.where(predicate.toArray(pre));return query.getRestriction();}

编写DAO类或接口 
dao类/接口 需继承

public interface JpaSpecificationExecutor<T>

接口; 
如果需要分页,还可继承

public interface PagingAndSortingRepository<T, ID extends Serializable> extends CrudRepository<T, ID>

JpaSpecificationExecutor 接口具有方法

Page<T> findAll(Specification<T> spec, Pageable pageable); //分页按条件查询

List<T> findAll(Specification<T> spec); //不分页按条件查询

方法。 我们可以在Service层调用这两个方法。 
两个方法都具有 Specification spec 参数,用于设定查询条件。 
Service 分页+多条件查询 调用示例:

studentInfoDao.findAll(new Specification<StudentInfo> () {  public Predicate toPredicate(Root<StudentInfo> root,  CriteriaQuery<?> query, CriteriaBuilder cb) {  Path<String> namePath = root.get("name");  Path<String> nicknamePath = root.get("nickname");  /** * 连接查询条件, 不定参数,可以连接0..N个查询条件 */  query.where(cb.like(namePath, "%李%"), cb.like(nicknamePath, "%王%")); //这里可以设置任意条查询条件  return null;  }  }, page);  }

  这里通过CriteriaBuilder 的like方法创建了两个查询条件, 姓名(name)字段必须包含“李”, 昵称(nickname)字段必须包含“王”。 
然后通过 
连接多个查询条件即可。 这种方式使用JPA的API设置了查询条件,所以不需要再返回查询条件Predicate给Spring Data Jpa,故最后return null;即可。

转载于:https://www.cnblogs.com/sandea/p/7803731.html

jpa多条件查询重写Specification的toPredicate方法(转)相关推荐

  1. springdata jpa jpql 条件查询

    jpql 条件为真,则添加条件查询:否则不添加条件查询: 参数是否为空,是则添加参数条件,否不添加 @Query(value="select eva.id as id,eva.userTyp ...

  2. jpa多表关联条件查询实现

    通过实体类映射实现多表关联条件查询 jpa对于多表关联可以在实体类中进行关联映射,一对一用@OneToOne,一对多用@OneToMany,多对多用@ManyToMany,多对一用@ManyToOne ...

  3. Spring boot JPA的复杂查询

    就很坑这个东西搞了一个下午的时间,终于搞会怎么用 对于想要查询 A and (B or C )或者 A And B And (C or D) 在jpa里你不能直接用and和or把字段拼起来,因为他并不 ...

  4. 【定区管理功能】定区列表分页条件查询

    [定区管理功能]定区列表分页条件查询 修改fixed_area.html页面,点击查询窗口中的查询按钮,将查询表单数据转换为json,绑定到datagrid上. //定区数据表格 $('#grid') ...

  5. jpa 动态查询条件 数组_Spring data jpa 复杂动态查询方式总结

    一.Spring data jpa 简介 首先JPA是Java持久层API,由Sun公司开发, 希望整合ORM技术,实现天下归一.  诞生的缘由是为了整合第三方ORM框架,建立一种标准的方式,目前也是 ...

  6. Spring data jpa 条件查询-按时间段查询

    Spring data jpa 条件查询-按时间段查询 @Overridepublic Page<泛型> findRecordList(int couponDetailId, int pa ...

  7. SpringData JPA条件查询、排序、分页查询

    前言 在刚开始学习的时候,在dao的定义的接口需要继承JpaRepository<T, ID>接口和JpaSpecificationExecutor< T >接口,但是一直以来 ...

  8. vue+node多条件查询 分页_SpringBoot+JPA框架分页、带条件查询等操作

    前言 最近研究JPA框架,初学SpringBoot时也简单学过,但是不是很深入,所以这次主要是说一些进阶且常用.实用的操作! 前置准备 创建两张表或者让JPA自动建表,任意选择!学生表 package ...

  9. Spring Data JPA 条件查询 分页查询

    条件查询 //Label : 实体类,传过来的参数 labelDao.findAll(new Specification<Label>(){@Overridepublic Predicat ...

最新文章

  1. 深度学习机器臂控制_深度学习新进展:可自建任务解决模型的机器人问世
  2. Kubernetes 弹性伸缩全场景解读(五) - 定时伸缩组件发布与开源
  3. 图论--欧拉回路(模板)
  4. 富文本 NSAttributedString
  5. LeetCode 1114. 按序打印
  6. ElasticSearch 集群监控
  7. python unittest接口测试_python+request+unittest 接口测试练习
  8. 成也DP,败也DP(AFO?)
  9. 【小安翻唱】檄!帝国华撃団
  10. Windows Server 2012 GUI与Core的切换
  11. Slate轨道工具使用(四)—根动画与位置
  12. 入手新吉他了--雅马哈F600
  13. C语言实现图的深度优先遍历和广度优先遍历
  14. 双线macd指标参数最佳设置_一文讲透双线MACD指标及其实战运用
  15. 在 Excel UiPath 中插入或删除行或列
  16. 使用gb2312乱码,utf-8正常
  17. 播放器初始化配置重点
  18. kubekey搭建K8s集群与kubeSphere容器云管理平台实战
  19. PHP是什么,能做什么,为什么用PHP
  20. BUUCTF MISC刷题笔记(一)

热门文章

  1. [语义]情感分析方向近况·0908
  2. 当一个解决方案下面有多个项目时,如果设置启动项?
  3. 工业级别sd卡存贮slc mlc tlc
  4. 使用VS2010编译MongoDB C++驱动详解
  5. 修改mysql表结构语句
  6. Qt Style Sheet 翻译(中)--类似css
  7. echarts常用方法,legend状态支持两张图片切换(四)
  8. 开篇有益-解析微软微服务架构eShopOnContainers(一)
  9. android keytool 不是内部命令或外部命令在 (win7下不能用的解决方法)
  10. ewebeditor下利用ckplayer增加html5 (mp4)全平台的支持