`
tanlan
  • 浏览: 203381 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

JPA2中的查询:类型安全与面向对象(2)

阅读更多

该文翻译自网络,原文地址:

http://www.developer.com/java/ent/article.php/3902911/Querying-in-JPA-2-Typesafe-and-Object-Oriented.htm

使用criteria 查询

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

 

//All Necessary Imports
@StaticMetamodel(Dept.class)
public class Dept_ {    
	public static volatile SingularAttribute<Dept, Integer> id;   
	public static volatile ListAttribute<Dept, Employee> employeeCollection;    
	public static volatile SingularAttribute<Dept, String> name;
}
//All Necessary Imports
@StaticMetamodel(Employee.class)
public class Employee_ {     
	public static volatile SingularAttribute<Employee, Integer> id;    
	public static volatile SingularAttribute<Employee, Integer> age;    
	public static volatile SingularAttribute<Employee, String> name;    
	public static volatile SingularAttribute<Employee, Dept> deptId;
}

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

 

CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<Employee> criteriaQuery = criteriaBuilder.createQuery(Employee.class);
Root<Employee> employee = criteriaQuery.from(Employee.class);
Predicate condition = criteriaBuilder.gt(employee.get(Employee_.age), 24);
criteriaQuery.where(condition);
TypedQuery<Employee> typedQuery = em.createQuery(criteriaQuery);
List<Employee> result = typedQuery.getResultList();

 

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

 

构建CriteriaQuery 实例

CriteriaQuery 对象必须在实体类型或嵌入式类型上的Criteria 查询上起作用。它通过调用 CriteriaBuilder, createQuery CriteriaBuilder.createTupleQuery 获得。CriteriaBuilder就像CriteriaQuery 的工厂一样。CriteriaBuilder工厂类是调用EntityManager.getCriteriaBuilder  EntityManagerFactory.getCriteriaBuilder而得。 Employee实体的 CriteriaQuery 对象以下面的方式创建:

 

CriteriaBuilder criteriaBuilder = emf.getCriteriaBuilder();
CriteriaQuery<Employee> criteriaQuery = cb.createQuery(Employee.class);
 

 

 

 

 

QueryRoot

AbstractQueryCriteriaQuery 接口的父类。它提供得到查询根的方法。Criteria查询的查询根定义了实体类型,能为将来导航获得想要的结果,它与SQL查询中的FROM子句类似。

Root实例也是类型化的,且定义了查询的FROM子句中能够出现的类型。查询根实例能通过传入一个实体类型给 AbstractQuery.from方法获得。Criteria查询,可以有多个查询根。Employee实体的查询根对象可以用以下的语法获得: 

 

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

 过滤Queries

 

过滤条件应用到SQL语句的FROM子句中。在criteria 查询中,查询条件通过Predicate Expression 实例应用到CriteriaQuery 对象上。这些条件使用 CriteriaQuery .where 方法应用到CriteriaQuery 对象上。CriteriaBuilder 也是作为Predicate 实例的工厂,Predicate 对象通过调用CriteriaBuilder 的条件方法( equalnotEqual gt gelt lebetweenlike等)创建。Predicate 实例也可以用Expression 实例的 isNull isNotNull  in方法获得,复合的Predicate 语句可以使用CriteriaBuilderand, or andnot 方法构建。

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

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

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

执行查询与获取元模型实例

EntityManager.createQuery(CriteriaQuery)方法调用时,一个可执行的查询实例会创建,该方法返回指定从 criteria 查询返回的实际类型的TypedQuery 对象。TypedQuery 接口是javax.persistence.Queryinterface.的子类型。在该片段中, TypedQuery 中指定的类型信息是Employee,调用getResultList时,查询就会得到执行 

TypedQuery<Employee> typedQuery = em.createQuery(criteriaQuery);

List<Employee> result = typedQuery.getResultList();

元模型实例通过调用 EntityManager.getMetamodel 方法获得,EntityType<Employee>的元模型实例通过调用Metamodel.entity(Employee.class)而获得,其被传入 CriteriaQuery.from 获得查询根。

Metamodel metamodel = em.getMetamodel();EntityType<Employee> 
Employee_ = metamodel.entity(Employee.class);
Root<Employee> empRoot = criteriaQuery.from(Employee_);

 也有可能调用Root.getModel方法获得元模型信息。类型 EntityType<Dept>的实例Dept_name属性可以调用getSingularAttribute 方法获得,它与String文本进行比较:

CriteriaQuery criteriaQuery = criteriaBuilder.createQuery();
Root<Dept> dept = criteriaQuery.from(Dept.class);
EntityType<Dept> Dept_ = dept.getModel();
Predicate testCondition = criteriaBuilder.equal(dept.get(Dept_.getSingularAttribute("name", String.class)), "Ecomm");

 对应的 SQL: SELECT * FROM dept WHERE name = 'Ecomm'

Expression

Expression对象用在查询语句的selectwherehaving子句中,该接口有 isNull, isNotNull  in方法,下面的代码片段展示了Expression.in的用法,employye的年龄检查在2024的。

CriteriaQuery<Employee> criteriaQuery = criteriaBuilder .createQuery(Employee.class);
Root<Employee> employee = criteriaQuery.from(Employee.class);
criteriaQuery.where(employee.get(Employee_.age).in(20, 24));
em.createQuery(criteriaQuery).getResultList();

 对应的SQL: SELECT * FROM employee WHERE age in (20, 24)

复合谓词

Criteria Query也允许开发者编写复合谓词,通过该查询可以为多条件测试下面的查询检查两个条件。首先,name属性是否以M开头,其次,employeeage属性是否是25。逻辑操作符and执行获得结果记录。

criteriaQuery.where(criteriaBuilder.and(criteriaBuilder.like(employee.get(Employee_.name), "M%"), criteriaBuilder.equal(employee.get(Employee_.age), 25)));
em.createQuery(criteriaQuery).getResultList();

 对应 SQL: SELECT * FROM employee  WHERE name LIKE 'M%' AND age = 25

连接查询

SQL中,连接跨多张表以获取查询结果,类似的实体连接通过调用 From.join 执行,连接帮助从一个实体导航到另一个实体以获得查询结果。

Rootjoin方法返回一个 Join<Dept, Employee>类型(也可以是SetJoin,ListJoinMapJoin 或者 CollectionJoin类型)。默认情况下,连接操作使用内连接,而外连接可以通过在join方法中指定JoinType参数为LEFTRIGHT来实现。

CriteriaQuery<Dept> cqDept = criteriaBuilder.createQuery(Dept.class);
Root<Dept> deptRoot = cqDept.from(Dept.class);
Join<Dept, Employee> employeeJoin = deptRoot.join(Dept_.employeeCollection);
cqDept.where(criteriaBuilder.equal(employeeJoin.get(Employee_.deptId).get(Dept_.id), 1));
TypedQuery<Dept> resultDept = em.createQuery(cqDept);
 对应的SQL: SELECT * FROM employee e, dept d  WHERE e.deptId = d.id and d.id = 1

 

5
4
分享到:
评论
6 楼 我爱吃酥饼 2017-07-07  
u012014301 写道
请问下Dept_这个类是要自己手动创建 还是可以根据实体类或者配置文件自动生成啊?



自动生产,eclipse和idea ide 工具,需要配置,具体的你可以加我qq522450654
5 楼 u012014301 2017-06-08  
请问下Dept_这个类是要自己手动创建 还是可以根据实体类或者配置文件自动生成啊?
4 楼 jiangli19192 2014-05-29  
请问Dept_.employeeCollection里面的Dept_从哪里来的
3 楼 307622798 2013-03-04  
讲解的很详细,谢谢,帮我解决了一个大问题!
2 楼 qianli 2012-02-07  
为何entityManager.getCriteriaBuilder()为空呢?
1 楼 寒光2008 2011-07-20  
引用

相关推荐

    JPA核心知识总结

    1. **JPA是什么**:JPA是一种ORM(对象关系映射)框架,它允许Java开发者以面向对象的方式处理数据,将Java对象映射到数据库中的表,从而简化数据库操作。 2. **JPA起源**:JPA最初由Sun Microsystems开发,作为EJB...

    Pro JPA 2版

    JPA通过JPQL(Java Persistence Query Language)提供了一种面向对象的查询语言,使得开发者可以使用类似SQL的语法查询实体,而无需关心底层数据库的具体实现细节。 4. 准则API(Criteria API) 第九章“Criteria ...

    jpa例子jpajpa

    Criteria API则提供了一个更强大且类型安全的查询构建方式。 5. **事务管理(Transaction)**: 在JPA中,事务是通过`EntityManager`进行管理的。你可以使用`begin()`, `commit()`和`rollback()`方法来控制事务的...

    JPA_2.0_中的动态类型安全查询

    在JPA 1.0中,JPQL是一种非常强大的查询语言,它允许开发者以面向对象的方式来构造查询。然而,JPQL查询是以字符串形式存在的,这就意味着即使语法错误也会被编译器忽略,只有在运行时才会抛出异常。如清单1所示: ...

    李勇JPA快速入门05_jpa中的查询

    JPA还提供了Criteria API,一种类型安全的查询方式,允许在编译时检查查询语法。Criteria API允许构建复杂的查询条件,动态组合查询,避免了字符串拼接引起的潜在错误。 3. **命名查询** 命名查询是在实体类的元...

    jpa使用说明(English)

    - **Querydsl 扩展**:介绍了一个用于查询构建的类型安全查询构建器框架。 - **Web 支持**:提供了集成 Web 层与 Repository 层的方法。 - **Repository 填充器**:描述了填充 Repository 数据的策略。 - **遗留...

    JPA教程(全部为PDF格式的电子书)

    5. **查询语言(JPQL)**:介绍了Java Persistence Query Language,一种面向对象的查询语言,类似于SQL。 6. ** Criteria API**:提供了一种类型安全的方式来构建动态查询,避免了字符串拼接造成的错误。 ### 第二...

    JPA技术:年初写的办公室OA系统

    4. **继承支持**: 支持单表继承、联合继承和多表继承,允许在数据库设计中实现面向对象的继承结构。 5. **事务管理**: JPA与JTA(Java Transaction API)结合,可以方便地进行事务控制,确保数据的一致性。 ### ...

    04_JPA详解_第一个JPA实例与JPA主键生成策略.zip

    通过JPA,开发者可以使用面向对象的方式来处理数据库操作,而不是直接编写SQL语句。 2. **实体(Entity)**: 在JPA中,实体类是Java对象,它们代表数据库表中的记录。通过在类上使用`@Entity`注解,JPA知道这个类是...

    jpa操作mysql数据库

    Criteria API提供了一种更动态和类型安全的方式来构建查询。 7. **分页查询**:在描述中提到了分页查询,这通常通过`javax.persistence.Query`的`setFirstResult()`和`setMaxResults()`方法实现。这两个方法分别...

    详细介绍 jpa 开发文档

    3. **JPA 查询**:JPA 支持两种主要的查询类型:原生 SQL 查询和 JPQL 查询。 - **Query 接口**:提供了执行查询的基础方法。 - **简单查询**:可以使用 Query 接口执行基本的查询操作。 - **使用参数查询**:...

    springboot+jpa+swagger 动态查询

    Querydsl是一个类型安全的查询语言,它可以与JPA、JDO、Hibernate等持久层技术配合使用,通过代码生成工具,将查询表达式转换为对应的SQL语句。Specification接口则是Spring Data JPA自带的一种动态查询方式,开发者...

    09_传智播客JPA详解_使用JPQL语句进行查询

    **JPQL(Java Persistence Query Language)**是JPA中的查询语言,类似于SQL,但它是面向对象的,用来查询和操作持久化实体。与SQL不同的是,JPQL主要处理对象,而不是数据库表。在本课程"09_传智播客JPA详解_使用...

    JPA连接数据库,非常详细

    JPA通过提供对象/关系映射(ORM)功能,使得开发人员可以使用面向对象的方式来操作数据库,而无需直接编写SQL语句。JPA简化了数据访问,并且支持事务管理,使得在Java应用中处理数据库变得更加方便。 在描述的场景...

    SpringBoot+JPA.zip

    SpringBoot简化了Spring应用的初始设置和配置,而Java Persistence API (JPA) 是Java平台上的一个标准,用于对象关系映射(ORM),使得Java开发者能够以面向对象的方式处理数据库操作。 在"SpringBoot+JPA.zip"这个...

    09_JPA详解_使用JPQL语句进行查询.zip

    9. ** Criteria API**:除了JPQL,JPA还提供了Criteria API,这是一种更强大且类型安全的查询方式,允许在运行时动态构建查询。 10. **命名查询(Named Queries)**:预先在实体类或persistence.xml文件中定义的...

    JPA Specification

    - **元模型**:元模型是JPA 2.0引入的新特性,它允许开发者使用类型安全的方式进行查询操作。通过反射机制自动生成对应的元模型类,使得查询更加直观易读。 ##### 2. 查询 - **JPQL (Java Persistence Query ...

    Spring Data JPA 笔记

    3. **Querydsl**:Spring Data JPA可以与Querydsl结合使用,提供更强大的类型安全的查询能力。Querydsl允许开发者用Java对象表达复杂的查询语句,避免了SQL注入问题。 4. **Specifications**:Spring Data JPA的`...

    jpa

    **JPA(Java Persistence API)**是Java平台上用于对象关系映射(ORM)的一个标准API,它为开发者提供了一种方便的方式来将Java类与数据库表进行对应,使得开发者可以使用面向对象的方式处理数据库操作,而无需过多...

    JPA-Hibernate包

    同时,Criteria API提供了一种类型安全的编程式查询方式。 **Hibernate特色功能:** 1. **HQL(Hibernate Query Language)**:Hibernate的扩展查询语言,比JPQL更强大,支持更多复杂的查询操作。 2. ** Criteria...

Global site tag (gtag.js) - Google Analytics