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

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

  1. 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实例过滤条件

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

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

  1. 1.复杂条件多表查询
  1. //需要查询的对象
  2. public class Qfjbxxdz {
  3. @Id
  4. @GeneratedValue(generator = "system-uuid")
  5. @GenericGenerator(name = "system-uuid", strategy = "uuid.hex")
  6. private String id;
  7. @OneToOne
  8. @JoinColumn(name = "qfjbxx")
  9. private Qfjbxx qfjbxx; //关联表
  10. private String fzcc;
  11. private String fzccName;
  12. @ManyToOne
  13. @JoinColumn(name = "criminalInfo")
  14. private CriminalInfo criminalInfo;//关联表
  15. @Column(length=800)
  16. private String bz;
  17. //get/set......
  18. }
  19.  
  20. //创建构造Specification的方法
  21. //这里我传入两个条件参数因为与前段框架有关,你们写的时候具体自己业务自行决断
  22. private Specification<Qfjbxxdz> getWhereClause(final JSONArray condetion,final JSONArray search) {
  23. return new Specification<Qfjbxxdz>() {
  24. @Override
  25. public Predicate toPredicate(Root<Qfjbxxdz> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
  26. List<Predicate> predicate = new ArrayList<>();
  27. Iterator<JSONObject> iterator = condetion.iterator();
  28. Predicate preP = null;
  29. while(iterator.hasNext()){
  30. JSONObject jsonObject = iterator.next();
  31. //注意:这里用的root.join 因为我们要用qfjbxx对象里的字段作为条件就必须这样做join方法有很多重载,使用的时候可以多根据自己业务决断
  32. Predicate p1 = cb.equal(root.join("qfjbxx").get("id").as(String.class),jsonObject.get("fzId").toString());
  33. Predicate p2 = cb.equal(root.get("fzcc").as(String.class),jsonObject.get("ccId").toString());
  34. if(preP!=null){
  35. preP = cb.or(preP,cb.and(p1,p2));
  36. }else{
  37. preP = cb.and(p1,p2);
  38. }
  39. }
  40. JSONObject jsonSearch=(JSONObject) search.get(0);
  41. Predicate p3=null;
  42. if(null!=jsonSearch.get("xm")&&jsonSearch.get("xm").toString().length()>0){
  43. p3=cb.like(root.join("criminalInfo").get("xm").as(String.class),"%"+jsonSearch.get("xm").toString()+"%");
  44. }
  45. Predicate p4=null;
  46. if(null!=jsonSearch.get("fzmc")&&jsonSearch.get("fzmc").toString().length()>0){
  47. p4=cb.like(root.join("qfjbxx").get("fzmc").as(String.class),"%"+jsonSearch.get("fzmc").toString()+"%");
  48. }
  49. Predicate preA;
  50. if(null!=p3&&null!=p4){
  51. Predicate preS =cb.and(p3,p4);
  52. preA =cb.and(preP,preS);
  53. }else if(null==p3&&null!=p4){
  54. preA=cb.and(preP,p4);
  55. }else if(null!=p3&&null==p4){
  56. preA=cb.and(preP,p3);
  57. }else{
  58. preA=preP;
  59. }
  60. predicate.add(preA);
  61. Predicate[] pre = new Predicate[predicate.size()];
  62. query.where(predicate.toArray(pre));
  63. return query.getRestriction();
  64. }

编写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 分页+多条件查询 调用示例:

  1. studentInfoDao.findAll(new Specification<StudentInfo> () {
  2.  
  3. public Predicate toPredicate(Root<StudentInfo> root,
  4. CriteriaQuery<?> query, CriteriaBuilder cb) {
  5. Path<String> namePath = root.get("name");
  6. Path<String> nicknamePath = root.get("nickname");
  7. /**
  8. * 连接查询条件, 不定参数,可以连接0..N个查询条件
  9. */
  10. query.where(cb.like(namePath, "%李%"), cb.like(nicknamePath, "%王%")); //这里可以设置任意条查询条件
  11.  
  12. return null;
  13. }
  14.  
  15. }, page);
  16.  
  17. }

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

jpa多条件查询重写Specification的toPredicate方法(转)的更多相关文章

  1. jpa多条件查询

    首先继承JpaSpecificationExecutor<T>接口 需要用到JpaSpecificationExecutor<T>中的Page<T> findAll ...

  2. angularJS 条件查询 品优购条件查询品牌(条件查询和列表展示公用方法解决思路 及 post请求混合参数提交方式)

    Brand.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> &l ...

  3. springboot jpa 多条件查询(多表)

    前几天写的,贴上来. 实体类. package com.syl.demo.daomain; import lombok.Data; import javax.persistence.*; /** * ...

  4. springboot jpa 多条件查询(单表)

    需要实现的功能: 多个搜索输入框:全部不填,则查出所有列表:填了条件,就按条件查找:填的条件个数不定. 方法实现的核心:jpa自带的Specification<T> (目前只需要单表,多表 ...

  5. Spring Boot Jpa 多条件查询+排序+分页

    事情有点多,于是快一个月没写东西了,今天补上上次说的. JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将 ...

  6. spring data jpa 组合条件查询封装

    /** * 定义一个查询条件容器 * @author lee * * @param <T> */ public class Criteria<T> implements Spe ...

  7. spring jpa : 多条件查询

    https://www.cnblogs.com/Donnnnnn/p/6277872.html 方式一: 第一步:EmpAccNumService package com.payease.scford ...

  8. 项目一:第四天 1、快递员的条件分页查询-noSession,条件查询 2、快递员删除(逻辑删除) 3、基于Apache POI实现批量导入区域数据 a)Jquery OCUpload上传文件插件使用 b)Apache POI读取excel文件数据

    1. 快递员的条件分页查询-noSession,条件查询 2. 快递员删除(逻辑删除) 3. 基于Apache POI实现批量导入区域数据 a) Jquery OCUpload上传文件插件使用 b) ...

  9. hbase 利用rowkey设计进行多条件查询

    摘要 本文主要内容是通过合理Hbase 行键(rowkey)设计实现快速的多条件查询,所采用的方法将所有要用于查询中的列经过一些处理后存储在rowkey中,查询时通过rowkey进行查询,提高rowk ...

随机推荐

  1. Unity3d---> IEnumerator

    Unity3d---> IEnumerator 2013-04-18 10:24 2162人阅读 评论(0) 收藏 举报 Unity3dc# using UnityEngine; using S ...

  2. [Javascirpt] Immediately-Invoked function!!! IMPORTANT

    var parkRides = [["Birch Bumpers", 40], ["Pines Plunge", 55], ["Cedar Coast ...

  3. struts2訪问servlet的API

    1.struts作为控制器,正常非常多时候要訪问到servlet的API.经常使用功能:   (1).获取请求參数,控制界面跳转   (2).把共享数据存储于request,session,servl ...

  4. NYOJ 113 字符串替换(C++STL解法)

    字符串替换 时间限制:3000 ms  |            内存限制:65535 KB 难度:2 描写叙述 编写一个程序实现将字符串中的全部"you"替换成"we& ...

  5. VS2010已停止工作,framework 4.0安装失败

    好久没在台式机上写程序了,今天打开一个解决方案,报错: 从来没有遇到这种情况,重新关闭解决方案,在菜单栏中打开解决方案说没有framework 4.0,其实我安装的是4.5 ,也有4.0,于是全部卸载 ...

  6. Field.setAccessible()方法

    http://blog.csdn.net/kjfcpua/article/details/8496911 java代码中,常常将一个类的成员变量置为private 在类的外面获取此类的私有成员变量的v ...

  7. SqlServer数据库分离与附加

    SQL Server提供了“分离/附加”数据库.“备份/还原”数据库.复制数据库等多种数据库的备份和恢复方法.这里介绍一种学习中常用的“分离/附加”方法,类似于大家熟悉的“文件拷贝”方法,即把数据库文 ...

  8. js 判断iframe是否加载完毕

      js 判断iframe是否加载完毕 CreationTime--2018年9月13日15点30分 Author:Marydon 1.javascript实现 window.onload = fun ...

  9. Eclipse 如何导入web项目

      Eclipse 如何导入web项目 CreateTime--2018年3月8日09:07:16 Author:Marydon 方法一:推荐使用 1.将web项目手动拷贝到Eclipse的工作空间下 ...

  10. 在启动vsftpd,有时会报错

    在启动vsftpd,有时会报错:C:>ftp 192.168.0.101Connected to 192.168.0.101.220 (vsFTPd 2.0.5)User (192.168.0. ...