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 动态查询的更多相关文章

  1. springboot整合spring Data JPA

    今天敲代码,一连串的错误,我也是服气~果然,我们不是在出bug,就是在找bug的路上…… 今天完成的是springboot整合spring data JPA ,出了一连串的错,真是头大 java.sq ...

  2. springboot集成Spring Data JPA数据查询

    1.JPA介绍 JPA(Java Persistence API)是Sun官方提出的Java持久化规范.它为Java开发人员提供了一种对象/关联映射工具来管理Java应用中的关系数据.它的出现主要是为 ...

  3. spring data jpa 动态查询(工具类封装)

    利用JPA的Specification<T>接口和元模型就实现动态查询了.但是这样每一个需要动态查询的地方都需要写一个这样类似的findByConditions方法,小型项目还好,大型项目 ...

  4. Spring Data JPA动态查询(多条件and)

    entity: @Entity @Table(name = "data_illustration") public class Test { @Id @GenericGenerat ...

  5. spring-boot (三) spring data jpa

    学习文章来自:http://www.ityouknow.com/spring-boot.html spring data jpa介绍 首先了解JPA是什么? JPA(Java Persistence ...

  6. spring data jpa 分页查询

    https://www.cnblogs.com/hdwang/p/7843405.html spring data jpa 分页查询   法一(本地sql查询,注意表名啥的都用数据库中的名称,适用于特 ...

  7. Spring Boot 整合Spring Data JPA

    Spring Boot整合Spring Data JPA 1)加入依赖 <dependency> <groupId>org.springframework.boot</g ...

  8. Spring Boot从入门到精通(九)整合Spring Data JPA应用框架

    JPA是什么? JPA全称Java Persistence API,是Sun官方提出的Java持久化规范.是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中. ...

  9. Spring Boot 入门系列(二十七)使用Spring Data JPA 自定义查询如此简单,完全不需要写SQL!

    前面讲了Spring Boot 整合Spring Boot JPA,实现JPA 的增.删.改.查的功能.JPA使用非常简单,只需继承JpaRepository ,无需任何数据访问层和sql语句即可实现 ...

随机推荐

  1. Mac开发者常用的工具

    http://www.oschina.net/news/53946/mac-dev-tools

  2. spark介绍3

  3. java学习(一)数据类型

    一.java的安装及环境变量的配置 http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.htm ...

  4. WebCalendar.js

    var cal;   var isFocus=false; //是否为焦点   var pickMode ={       "second":1,       "minu ...

  5. 织梦CMS让channelartlist标签支持currentstyle【转】

    打开include\taglib\channelartlist.lib.php找到 $pv->Fields['typeurl'] = GetOneTypeUrlA($typeids[$i]); ...

  6. 查看iptables状态-重启

    iptables 所在目录 /etc/sysconfig/iptables service iptables status 查看iptables状态 service iptables restart ...

  7. MySQL数据库(三)

    1. 创建表 create table student( id int unsigned not null auto_increment primary key, name varchar(8) no ...

  8. NVIDIA GTC照片

    这次的NVIDIA GPU Technology Conference 2014在美国San Jose(就是俗称的硅谷了)举办. 去美国的飞机上10个小时反正是睡不着,电影还是挺好看的. 美联航的早餐 ...

  9. RHEL因为selinux设置失误,无法重启问题。(centos适用)

    今天做FTP模拟的时候selinux设置出现失误.导致系统无法重新启动.出现如下界面 Failed To Load SELinux policy.freezing .. 网上找了下,解决方法如下: 开 ...

  10. DIOCP (一) DIOCP常见问题。

    1,IOCP是什么? 答:IOCP是windows下的服务器技术,并不是所有windows都能使用IOCP,只能在支持IOCP的windows操作系统上使用. 2,DIOCP是什么? 答:DIOCP是 ...