Spring Data JPA虽然大大的简化了持久层的开发,但是在实际开发中,很多地方都需要高级动态查询,在实现动态查询时我们需要用到Criteria API,主要是以下三个:
1、Criteria 查询是以元模型的概念为基础的,元模型是为具体持久化单元的受管实体定义的,这些实体可以是实体类,嵌入类或者映射的父类。
2、CriteriaQuery接口:代表一个specific的顶层查询对象,它包含着查询的各个部分,比如:select 、from、where、group by、order by等注意:CriteriaQuery对象只对实体类型或嵌入式类型的Criteria查询起作用
3、Root接口:代表Criteria查询的根对象,Criteria查询的查询根定义了实体类型,能为将来导航获得想要的结果,它与SQL查询中的FROM子句类似
在JPA中,标准查询是以元模型的概念为基础的.元模型是为具体持久化单元的受管实体定义的.这些实体可以是实体类,嵌入类或者映射的父类.提供受管实体元信息的类就是元模型类。使用元模型类最大的优势是凭借其实例化可以在编译时访问实体的持久属性.该特性使得criteria 查询更加类型安全。例如:Product实体类对应的元模型Product_:
package powerx.io.bean; import javax.annotation.Generated;
import javax.persistence.metamodel.SingularAttribute;
import javax.persistence.metamodel.StaticMetamodel; @Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor")
@StaticMetamodel(Product.class)
public abstract class Product_ { public static volatile SingularAttribute<Product, Double> price;
public static volatile SingularAttribute<Product, String> name;
public static volatile SingularAttribute<Product, Integer> id; }
这样的元模型不用手动创建,有多种构建方式,本人使用的IDE是STS,具体操作如下:选中项目——鼠标右键Properties进入配置界面——java compiler下Annotation Processing——勾选enable project specific settings——Annotation Processing下Factory path——add external JARs ——加入事先下载好的hibernate-jpamodelgen-5.2.10.Final.jar——apply后则会在项目根目录下生成.apt_generated包,包内含有对应的实体类元模型(看不到的同学需要把resource过滤去掉),还有其它的方式,可参考http://docs.jboss.org/hibernate/jpamodelgen/1.0/reference/en-US/html/chapter-usage.html。
使用criteria 查询简单Demo
@Resource
private EntityManager entityManager; public List<Product> findByConditions(String name, Double price) {
//创建CriteriaBuilder安全查询工厂
//CriteriaBuilder是一个工厂对象,安全查询的开始.用于构建JPA安全查询.
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
//创建CriteriaQuery安全查询主语句
//CriteriaQuery对象必须在实体类型或嵌入式类型上的Criteria 查询上起作用。
CriteriaQuery<Product> query = criteriaBuilder.createQuery(Product.class);
//Root 定义查询的From子句中能出现的类型
Root<Product> ProductRoot = query.from(Product.class);
//Predicate 过滤条件 构建where字句可能的各种条件
//这里用List存放多种查询条件,实现动态查询
List<Predicate> predicatesList = new ArrayList<>();
//name模糊查询 ,like语句
if (name != null) {
predicatesList.add(
criteriaBuilder.and(
criteriaBuilder.like(
ProductRoot.get(Product_.name), "%" + name + "%")));
}
// ProductPrice 小于等于 <= 语句
if (price != null) {
predicatesList.add(
criteriaBuilder.and(
criteriaBuilder.le(
ProductRoot.get(Product_.price), price)));
} query.where(predicatesList.toArray(new Predicate[predicatesList.size()]));
TypedQuery<Product> typedQuery = entityManager.createQuery(query);
List<Product> resultList = typedQuery.getResultList();
return resultList;
}
criteriaBuilder中各方法对应的语句:
equle : filed = value
gt / greaterThan : filed > value
lt / lessThan : filed < value
ge / greaterThanOrEqualTo : filed >= value
le / lessThanOrEqualTo: filed <= value
notEqule : filed != value
like : filed like value
notLike : filed not like value
如果每个动态查询的地方都这么写,那就感觉太麻烦了。那实际上,在使用Spring Data JPA的时候,只要我们的Repo层接口继承JpaSpecificationExecutor接口就可以使用Specification进行动态查询,在这里因为findAll(Specification<T> var1, Pageable var2)
方法中参数 Specification<T>
是一个匿名内部类
那这里就可以直接用lambda表达式直接简化代码。
持久层接口类:
package powerx.io; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import powerx.io.bean.Product; public interface ProductDao extends JpaRepository<Product, Integer>,JpaSpecificationExecutor<Product> { }
service层:
@Autowired
private ProductDao productDao; public List<Product> findByConditions2(String name, Double price) {
return productDao.findAll((root, criteriaQuery, criteriaBuilder) -> {
List<Predicate> predicatesList = new ArrayList<>();
if (name != null) {
predicatesList.add(
criteriaBuilder.and(
criteriaBuilder.like(
root.get(Product_.name), "%" + name + "%")));
}
// itemPrice 小于等于 <= 语句
if (price != null) {
predicatesList.add(
criteriaBuilder.and(
criteriaBuilder.le(
root.get(Product_.price), price)));
}
return criteriaBuilder.and(
predicatesList.toArray(new Predicate[predicatesList.size()]));
});
}
控制器类:
package powerx.io; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; @RestController
public class ProductController { @Autowired
private ProductServiceImpl productServiceImpl; @GetMapping("/find")
public Object find(@RequestParam String name ,@RequestParam Double price) {
return productServiceImpl.findByConditions2(name, price);
}
}
实体类:
package powerx.io.bean; import java.io.Serializable; import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id; @Entity
public class Product implements Serializable{ private static final long serialVersionUID = 5800591455207338888L; @Id
@GeneratedValue
private Integer id; private String name; private Double price; public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Double getPrice() {
return price;
} public void setPrice(Double price) {
this.price = price;
} }
使用springboot构建项目,pom.xml 和application.yml如下
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <!-- 连接mysql数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency> <!-- 整合jpa -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
spring:
datasource:
url: jdbc:mysql://localhost:3306/springdatajpa
username: root
password: root
jpa:
show-sql: true
hibernate:
ddl-auto: update
启动项目,会根据实体类自动创建对应的表,加入测试数据,访问http://localhost:8080/find?name=apple&price=88,结果如下:
参考文章:https://www.jianshu.com/p/0939cec7e207
springboot整合spring data jpa 动态查询的更多相关文章
-
springboot整合spring Data JPA
今天敲代码,一连串的错误,我也是服气~果然,我们不是在出bug,就是在找bug的路上…… 今天完成的是springboot整合spring data JPA ,出了一连串的错,真是头大 java.sq ...
-
springboot集成Spring Data JPA数据查询
1.JPA介绍 JPA(Java Persistence API)是Sun官方提出的Java持久化规范.它为Java开发人员提供了一种对象/关联映射工具来管理Java应用中的关系数据.它的出现主要是为 ...
-
spring data jpa 动态查询(工具类封装)
利用JPA的Specification<T>接口和元模型就实现动态查询了.但是这样每一个需要动态查询的地方都需要写一个这样类似的findByConditions方法,小型项目还好,大型项目 ...
-
Spring Data JPA动态查询(多条件and)
entity: @Entity @Table(name = "data_illustration") public class Test { @Id @GenericGenerat ...
-
spring-boot (三) spring data jpa
学习文章来自:http://www.ityouknow.com/spring-boot.html spring data jpa介绍 首先了解JPA是什么? JPA(Java Persistence ...
-
spring data jpa 分页查询
https://www.cnblogs.com/hdwang/p/7843405.html spring data jpa 分页查询 法一(本地sql查询,注意表名啥的都用数据库中的名称,适用于特 ...
-
Spring Boot 整合Spring Data JPA
Spring Boot整合Spring Data JPA 1)加入依赖 <dependency> <groupId>org.springframework.boot</g ...
-
Spring Boot从入门到精通(九)整合Spring Data JPA应用框架
JPA是什么? JPA全称Java Persistence API,是Sun官方提出的Java持久化规范.是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中. ...
-
Spring Boot 入门系列(二十七)使用Spring Data JPA 自定义查询如此简单,完全不需要写SQL!
前面讲了Spring Boot 整合Spring Boot JPA,实现JPA 的增.删.改.查的功能.JPA使用非常简单,只需继承JpaRepository ,无需任何数据访问层和sql语句即可实现 ...
随机推荐
-
Linux SendMail服务启动慢总结
在 CentOS release 6.6 上启动sendmail服务时发现服务启动过程非常慢,基本上要耗费3分多钟.有点纳闷:什么原因导致sendmail启动这么慢?搜索了这方面的一些资料,结合自己的 ...
-
Linux提权(1)-基础版~
利用Linux内核漏洞提权 VulnOS version 2是VulHub上的一个Linux提权练习,当打开虚拟机后,可以看到 获取到低权限SHELL后我们通常做下面几件事 1.检测操作系统的发行版本 ...
-
【转】C++中的虚函数的实现
转自:http://blog.csdn.net/haoel/article/details/1948051 对C++ 了解的人都应该知道虚函数(Virtual Function)是通过一张虚函数表(V ...
-
Linux libtins 库安装教程
因为工作原因需要用到libtins网络库, 所以今天去装一下. 很尴尬,由于本人对linux理解比较浅, 所以在中途遇到了一些问题. 虽然只是简单的安装步骤,但是阻挡不了自己菜啊. 一. 下载lib ...
-
Apache设置404页面
使用版本:Apache 2.2 1.添加404页面 在所配置网站的根目录添加编辑好的 404.html (页面名字无所谓 比如也可以叫missing.html) 如C:\Program Files\A ...
-
Hystrix-request collapsing(请求合并)
介绍: Hystrix的请求合并就是把重复的请求批量的用一个HystrixCommand命令去执行,以减少通信消耗和线程数的占用.Hystrix的请求合并用到了HystrixCollapser这个抽象 ...
-
【oauth2.0】【1】简单介绍
含义: OAuth是一个关于授权(authorization)的开放网络标准,2.0是当前版本.不是技术,而是一项资源授权协议. OAuth在"客户端"与"服务提供商&q ...
-
MATLAB 求两个矩阵的 欧氏距离
欧式距离定义: 欧式距离公式有如下几种表示方法: MATLAB 求两个矩阵的 欧氏距离 : 如果定义两个矩阵分别为a,b则定义c=(a-b).^2所求距离d=sqrt(sum(c(:)))
-
接Window服务(二)
接Window服务(一) ServiceController方法调用 1 public partial class Service1 : ServiceBase 2 { 3 public Servic ...
-
Android-解析JSON数据(JSON对象/JSON数组)
在上一篇博客中,Android-封装JSON数据(JSON对象/JSON数组),讲解到Android真实开发中更多的是去解析JSON数据(JSON对象/JSON数组) 封装JSON的数据是在服务器端进 ...