项目中使用jpa ,第一次见查询起来一脸蒙,这就去查下jpa查询的方式,和概念。java
jpa
概念
建立使用Java Persistence API的存储库是一个繁琐的过程,须要大量时间并须要大量样板代码。一种推荐的方式是使用元python
元模型
概念
在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_ui
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规范中描述的如下规则在相应的元模型类中映射:this
元模型类的属性所有是static和public的。
元模型类的属性所有是static和public的。Employee的每个属性都会使用在JPA2规范中描述的如下规则在相应的元模型类中映射:spa
对于Addess这样的集合类型,会定义静态属性ListAttribute< A, B> b,这里List对象b是定义在类A中类型B的对象。其它集合类型能够是SetAttribute, MapAttribute 或 CollectionAttribute 类型。.net
看到这应该会有个疑问,这麻烦,为何要使用这个元模型?有啥好处?
好处确定是有的,毕竟是标准jpa定义的东西。我这网上查了下,好处不少:code
查询更加类型安全
好吧,我暂时就查到这个。对象
criteria 查询
为了更好的理解criteria 查询,考虑拥有Employee实例集合的Dept实体,Employee和Dept的元模型类的代码以下:blog
//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)) + "%"));
写博客是为了记住本身容易忘记的东西,另外也是对本身工做的总结,文章能够转载,无需版权。但愿尽本身的努力,作到更好,你们一块儿努力进步!
若是有什么问题,欢迎你们一块儿探讨,代码若有问题,欢迎各位大神指正!