3 Spring JPA Specification 查询

2024-05-01 12:38

本文主要是介绍3 Spring JPA Specification 查询,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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实例
过滤条件
1:过滤条件会被应用到SQL语句的FROM子句中。在criteria 查询中,查询条件通过Predicate或Expression实例应用到CriteriaQuery对象上。
2:这些条件使用 CriteriaQuery .where 方法应用到CriteriaQuery 对象上
3:CriteriaBuilder也作为Predicate实例的工厂,通过调用CriteriaBuilder 的条件方法( equal,notEqual, gt, ge,lt, le,between,like等)创建Predicate对象。
4:复合的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));
当然也可以形如前面动态拼接查询语句的方式,比如:

java代码:
查看 复制到剪贴板 打印
  1. Specification<UserModel> spec = new Specification<UserModel>() {  
  2. public Predicate toPredicate(Root<UserModel> root,  
  3.         CriteriaQuery<?> query, CriteriaBuilder cb) {  
  4.     List<Predicate> list = new ArrayList<Predicate>();  
  5.           
  6.     if(um.getName()!=null && um.getName().trim().length()>0){  
  7.         list.add(cb.like(root.get("name").as(String.class), "%"+um.getName()+"%"));  
  8.     }  
  9.     if(um.getUuid()>0){  
  10.         list.add(cb.equal(root.get("uuid").as(Integer.class), um.getUuid()));  
  11.     }  
  12.     Predicate[] p = new Predicate[list.size()];  
  13.     return cb.and(list.toArray(p));  
  14. }  
  15. };  

 
也可以使用CriteriaQuery来得到最后的Predicate,示例如下:
  
java代码:
查看 复制到剪贴板 打印
  1. Specification<UserModel> spec = new Specification<UserModel>() {  
  2.     public Predicate toPredicate(Root<UserModel> root,  
  3.             CriteriaQuery<?> query, CriteriaBuilder cb) {  
  4.         Predicate p1 = cb.like(root.get("name").as(String.class), "%"+um.getName()+"%");  
  5.         Predicate p2 = cb.equal(root.get("uuid").as(Integer.class), um.getUuid());  
  6.         Predicate p3 = cb.gt(root.get("age").as(Integer.class), um.getAge());  
  7.         //把Predicate应用到CriteriaQuery中去,因为还可以给CriteriaQuery添加其他的功能,比如排序、分组啥的  
  8.         query.where(cb.and(p3,cb.or(p1,p2)));  
  9.         //添加排序的功能  
  10.         query.orderBy(cb.desc(root.get("uuid").as(Integer.class)));  
  11.           
  12.         return query.getRestriction();  
  13.     }  
  14. };  
多表联接
n多表连接查询稍微麻烦一些,下面演示一下常见的1:M,顺带演示一下1:1
n使用Criteria查询实现1对多的查询
1:首先要添加一个实体对象DepModel,并设置好UserModel和它的1对多关系,如下:
@Entity
@Table(name="tbl_user")
public class UserModel {
@Id
private Integer uuid;
private String name;
private Integer age;
@OneToMany(mappedBy = "um", fetch = FetchType.  LAZY, cascade = {CascadeType.  ALL})
private Set<DepModel> setDep;
//省略getter/setter
}
@Entity
@Table(name="tbl_dep")
public class DepModel {
@Id
private Integer uuid;
private String name;
@ManyToOne()
@JoinColumn(name = "user_id", nullable = false)
//表示在tbl_dep里面有user_id的字段
private UserModel um = new UserModel();
//省略getter/setter
}
2:配置好Model及其关系后,就可以在构建Specification的时候使用了,示例如下:
Specification<UserModel> spec = new Specification<UserModel>() {
public Predicate toPredicate(Root<UserModel> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
Predicate p1 = cb.like(root.get("name").as(String.class), "%"+um.getName()+"%");
Predicate p2 = cb.equal(root.get("uuid").as(Integer.class), um.getUuid());
Predicate p3 = cb.gt(root.get("age").as(Integer.class), um.getAge());
SetJoin<UserModel,DepModel> depJoin = root.join(root.getModel().getSet("setDep",DepModel.class) , JoinType.LEFT);
Predicate p4 = cb.equal(depJoin.get("name").as(String.class), "ddd");
//把Predicate应用到CriteriaQuery去,因为还可以给CriteriaQuery添加其他的功能,比如排序、分组啥 的
query.where(cb.and(cb.and(p3,cb.or(p1,p2)),p4));
//添加分组的功能
query.orderBy(cb.desc(root.get("uuid").as(Integer.class)));
return query.getRestriction();
}};
n接下来看看使用Criteria查询实现1:1的查询
1:在UserModel中去掉setDep的属性及其配置,然后添加如下的属性和配置:
@OneToOne()
@JoinColumn(name = "depUuid")
private DepModel dep;
public DepModel getDep() { return dep;}
public void setDep(DepModel dep) {this.dep = dep;  }
2:在DepModel中um属性上的注解配置去掉,换成如下的配置:
@OneToOne(mappedBy = "dep", fetch = FetchType.  EAGER, cascade = {CascadeType.  ALL})
3:在Specification实现中,把SetJoin的那句换成如下的语句:
Join<UserModel,DepModel> depJoin =
root.join(root.getModel().getSingularAttribute("dep",DepModel.class),JoinType.LEFT);
//root.join(“dep”,JoinType.LEFT); //这句话和上面一句的功能一样,更简单

这篇关于3 Spring JPA Specification 查询的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/951716

相关文章

Spring Boot集成/输出/日志级别控制/持久化开发实践

《SpringBoot集成/输出/日志级别控制/持久化开发实践》SpringBoot默认集成Logback,支持灵活日志级别配置(INFO/DEBUG等),输出包含时间戳、级别、类名等信息,并可通过... 目录一、日志概述1.1、Spring Boot日志简介1.2、日志框架与默认配置1.3、日志的核心作用

破茧 JDBC:MyBatis 在 Spring Boot 中的轻量实践指南

《破茧JDBC:MyBatis在SpringBoot中的轻量实践指南》MyBatis是持久层框架,简化JDBC开发,通过接口+XML/注解实现数据访问,动态代理生成实现类,支持增删改查及参数... 目录一、什么是 MyBATis二、 MyBatis 入门2.1、创建项目2.2、配置数据库连接字符串2.3、入

Springboot项目启动失败提示找不到dao类的解决

《Springboot项目启动失败提示找不到dao类的解决》SpringBoot启动失败,因ProductServiceImpl未正确注入ProductDao,原因:Dao未注册为Bean,解决:在启... 目录错误描述原因解决方法总结***************************APPLICA编

深度解析Spring Security 中的 SecurityFilterChain核心功能

《深度解析SpringSecurity中的SecurityFilterChain核心功能》SecurityFilterChain通过组件化配置、类型安全路径匹配、多链协同三大特性,重构了Spri... 目录Spring Security 中的SecurityFilterChain深度解析一、Security

SpringBoot多环境配置数据读取方式

《SpringBoot多环境配置数据读取方式》SpringBoot通过环境隔离机制,支持properties/yaml/yml多格式配置,结合@Value、Environment和@Configura... 目录一、多环境配置的核心思路二、3种配置文件格式详解2.1 properties格式(传统格式)1.

Apache Ignite 与 Spring Boot 集成详细指南

《ApacheIgnite与SpringBoot集成详细指南》ApacheIgnite官方指南详解如何通过SpringBootStarter扩展实现自动配置,支持厚/轻客户端模式,简化Ign... 目录 一、背景:为什么需要这个集成? 二、两种集成方式(对应两种客户端模型) 三、方式一:自动配置 Thick

Spring WebClient从入门到精通

《SpringWebClient从入门到精通》本文详解SpringWebClient非阻塞响应式特性及优势,涵盖核心API、实战应用与性能优化,对比RestTemplate,为微服务通信提供高效解决... 目录一、WebClient 概述1.1 为什么选择 WebClient?1.2 WebClient 与

Java.lang.InterruptedException被中止异常的原因及解决方案

《Java.lang.InterruptedException被中止异常的原因及解决方案》Java.lang.InterruptedException是线程被中断时抛出的异常,用于协作停止执行,常见于... 目录报错问题报错原因解决方法Java.lang.InterruptedException 是 Jav

深入浅出SpringBoot WebSocket构建实时应用全面指南

《深入浅出SpringBootWebSocket构建实时应用全面指南》WebSocket是一种在单个TCP连接上进行全双工通信的协议,这篇文章主要为大家详细介绍了SpringBoot如何集成WebS... 目录前言为什么需要 WebSocketWebSocket 是什么Spring Boot 如何简化 We

java中pdf模版填充表单踩坑实战记录(itextPdf、openPdf、pdfbox)

《java中pdf模版填充表单踩坑实战记录(itextPdf、openPdf、pdfbox)》:本文主要介绍java中pdf模版填充表单踩坑的相关资料,OpenPDF、iText、PDFBox是三... 目录准备Pdf模版方法1:itextpdf7填充表单(1)加入依赖(2)代码(3)遇到的问题方法2:pd