java中的criteria_java-jpa-criteriaBuilder使用入门

项目中使用jpa ,第一次见查询起来一脸蒙,这就去查下jpa查询的方式,和概念。

jpa

概念

创建使用Java Persistence API的存储库是一个繁琐的过程,需要大量时间并需要大量样板代码。一种推荐的方式是使用元

元模型

概念

在JPA中,标准查询是以元模型的概念为基础的,元模型是为具体持久化单元的受管实体定义的.这些实体可以是实体类,嵌入类或者映射的父类.提供受管实体元信息的类就是元模型类.

简单的说就是元模型是实体类对应的一个“受管实体

- 举个例子:

实体类 Employee(com.demo.entities包中定义)

@Entity

@Table

public class Employee{

private int id;

private String name;

private int age;

@OneToMany

private List

addresses;

// Other code…

}

1

2

3

4

5

6

7

8

9

10

Employee类的标准元模型类的名字是 Employee_

import javax.annotation.Generated;

import javax.persistence.metamodel.SingularAttribute;

import javax.persistence.metamodel.ListAttribute;

import javax.persistence.metamodel.StaticMetamodel;

@StaticMetamodel(Employee.class)

public class Employee_ {

public static volatile SingularAttribute id;

public static volatile SingularAttribute age;

public static volatile SingularAttribute name;

public static volatile ListAttribute addresses;

}

1

2

3

4

5

6

7

8

9

10

11

Employee的每一个属性都会使用在JPA2规范中描述的以下规则在相应的元模型类中映射:

元模型类的属性全部是static和public的。

元模型类的属性全部是static和public的。Employee的每一个属性都会使用在JPA2规范中描述的以下规则在相应的元模型类中映射:

对于Addess这样的集合类型,会定义静态属性ListAttribute< A, B> b,这里List对象b是定义在类A中类型B的对象。其它集合类型可以是SetAttribute, MapAttribute 或 CollectionAttribute 类型。

看到这应该会有个疑问,这麻烦,为什么要使用这个元模型?有啥好处?

好处肯定是有的,毕竟是标准jpa定义的东西。我这网上查了下,好处很多:

查询更加类型安全

好吧,我暂时就查到这个。

criteria 查询

为了更好的理解criteria 查询,考虑拥有Employee实例集合的Dept实体,Employee和Dept的元模型类的代码如下:

//All Necessary Imports

@StaticMetamodel(Dept.class)

public class Dept_ {

public static volatile SingularAttribute id;

public static volatile ListAttribute employeeCollection;

public static volatile SingularAttribute name;

}

//All Necessary Imports

@StaticMetamodel(Employee.class)

public class Employee_ {

public static volatile SingularAttribute id;

public static volatile SingularAttribute age;

public static volatile SingularAttribute name;

public static volatile SingularAttribute deptId;

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

下面的代码片段展示了一个criteria 查询,它用于获取所有年龄大于24岁的员工:

CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();

CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Employee.class);

Root employee = criteriaQuery.from(Employee.class);

Predicate condition = criteriaBuilder.gt(employee.get(Employee_.age), 24);

criteriaQuery.where(condition);

TypedQuery typedQuery = em.createQuery(criteriaQuery);

List result = typedQuery.getResultList();

1

2

3

4

5

6

7

对应的SQL: SELECT * FROM employee WHERE age > 24

CriteriaBuilder 安全查询创建工厂

CriteriaBuilder 安全查询创建工厂,,创建CriteriaQuery,创建查询具体具体条件Predicate 等。

CriteriaBuilder是一个工厂对象,安全查询的开始.用于构建JPA安全查询.可以从EntityManager 或 EntityManagerFactory类中获得CriteriaBuilder。

比如:

CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();

CriteriaQuery 安全查询主语句

它通过调用 CriteriaBuilder, createQuery 或CriteriaBuilder.createTupleQuery 获得。

CriteriaBuilder就像CriteriaQuery 的工厂一样。

CriteriaQuery对象必须在实体类型或嵌入式类型上的Criteria 查询上起作用。

Employee实体的 CriteriaQuery 对象以下面的方式创建:

CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();

CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Employee.class);

1

2

Root

Root 定义查询的From子句中能出现的类型

Criteria查询的查询根定义了实体类型,能为将来导航获得想要的结果,它与SQL查询中的FROM子句类似。

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

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

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

Employee实体的查询根对象可以用以下的语法获得 :

Root employee = criteriaQuery.from(Employee.class);

1

Predicate 过滤条件

过滤条件应用到SQL语句的FROM子句中。

在criteria 查询中,查询条件通过Predicate 或Expression 实例应用到CriteriaQuery 对象上。

这些条件使用 CriteriaQuery .where 方法应用到CriteriaQuery 对象上。

Predicate 实例也可以用Expression 实例的 isNull, isNotNull 和 in方法获得,复合的Predicate 语句可以使用CriteriaBuilder的and, or andnot 方法构建。

CriteriaBuilder 也是作为Predicate 实例的工厂,Predicate 对象通过调用CriteriaBuilder 的条件方法( equal,notEqual, gt, ge,lt, le,between,like等)创建。

这些条件使用 CriteriaQuery .where 方法应用到CriteriaQuery 对象上。

下面的代码片段展示了Predicate 实例检查年龄大于24岁的员工实例:

Predicate condition = criteriaBuilder.gt(employee.get(Employee_.age), 24);

criteriaQuery.where(condition);

1

2

过Employee_元模型类age属性,称之为路径表达式。若age属性与String文本比较,编译器会抛出错误,这在JPQL中是不可能的。这就是元模型的作用吗??

Predicate[] 多个过滤条件

List predicatesList = new ArrayList();

predicatesList.add(.....Pridicate....)

criteriaQuery.where(predicatesList.toArray(new Predicate[predicatesList.size()]));

OR语句(可怕)

predicatesList.add(criteriaBuilder.or(criteriaBuilder.equal(root.get(RepairOrder_.localRepairStatus), LocalRepairStatus.repairing),criteriaBuilder.equal(root.get(RepairOrder_.localRepairStatus), LocalRepairStatus.diagnos)));

忽略大小写(全大写)

predicatesList.add(criteriaBuilder.like(criteriaBuilder.upper(root.get(RepairShop_.shopName)), StringUtils.upperCase(StringUtils.trim(this.shopName)) + "%"));

写博客是为了记住自己容易忘记的东西,另外也是对自己工作的总结,文章可以转载,无需版权。希望尽自己的努力,做到更好,大家一起努力进步!

如果有什么问题,欢迎大家一起探讨,代码如有问题,欢迎各位大神指正!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值