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

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

阅读更多

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

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

抓取连接

当涉及到collection属性时,抓取连接对优化数据访问是非常有帮助的。这是通过预抓取关联对象和减少懒加载开销而达到的。使用 criteria 查询,fetch方法用于指定关联属性

Fetch连接的语义与Join是一样的,因为Fetch操作不返回Path对象,所以它不能将来在查询中引用。在以下例子中,查询Dept对象时employeeCollection对象被加载,这不会有第二次查询数据库,因为有懒加载。

 

CriteriaQuery<Dept> d = cb.createQuery(Dept.class);
Root<Dept> deptRoot = d.from(Dept.class);
deptRoot.fetch("employeeCollection", JoinType.LEFT);
d.select(deptRoot);
List<Dept> dList = em.createQuery(d).getResultList(); 

对应SQL: SELECT * FROM dept d, employee e  WHERE d.id = e.deptId

 

路径表达式

Root实例,Join实例或者从另一个Path对象的get方法获得的对象使用get方法可以得到Path对象,当查询需要导航到实体的属性时,路径表达式是必要的。Get方法接收的参数是在实体元模型类中指定的属性。Path对象一般用于Criteria查询对象的selectwhere方法。例子如下:

 

CriteriaQuery<String> criteriaQuery = criteriaBuilder.createQuery(String.class);
Root<Dept> root = criteriaQuery.from(Dept.class);
criteriaQuery.select(root.get(Dept_.name)); 

参数化表达式

     在JPQL中,查询参数是在运行时通过使用命名参数语法(冒号加变量,如 :age)传入的。在Criteria查询中,查询参数是在运行时创建ParameterExpression对象并为在查询前调用TypeQuery,setParameter方法设置而传入的。下面代码片段展示了类型为IntegerParameterExpression age,它被设置为24

 

ParameterExpression<Integer> age = criteriaBuilder.parameter(Integer.class);
Predicate condition = criteriaBuilder.gt(testEmp.get(Employee_.age), age);
criteriaQuery.where(condition);
TypedQuery<Employee> testQuery = em.createQuery(criteriaQuery);
List<Employee> result = testQuery.setParameter(age, 24).getResultList();
Corresponding SQL: SELECT * FROM Employee WHERE age = 24 

排序结果

 

     Criteria查询的结果能调用CriteriaQuery.orderBy方法排序,该方法接收一个Order对象做为参数。通过调用  CriteriaBuilder.asc CriteriaBuilder.DescOrder对象能被创建。以下代码片段中,Employee实例是基于age的升序排列。 

 

CriteriaQuery<Employee> criteriaQuery = criteriaBuilder .createQuery(Employee.class);
 Root<Employee> employee = criteriaQuery.from(Employee.class);
 criteriaQuery.orderBy(criteriaBuilder.asc(employee.get(Employee_.age)));
  em.createQuery(criteriaQuery).getResultList();

 

  对应 SQL: SELECT * FROM Employee ORDER BY age ASC

 

分组

CriteriaQuery 实例的groupBy 方法用于基于Expression的结果分组。查询通过设置额外表达式,以后调用having方法。下面代码片段中,查询按照Employee类的name属性分组,且结果以字母N开头:

 

 CriteriaQuery<Tuple> cq = criteriaBuilder.createQuery(Tuple.class);

  Root<Employee> employee = cq.from(Employee.class);
  cq.groupBy(employee.get(Employee_.name));
  cq.having(criteriaBuilder.like(employee.get(Employee_.name), "N%"));
cq.select(criteriaBuilder.tuple(employee.get(Employee_.name),criteriaBuilder.count(employee)));
  TypedQuery<Tuple> q = em.createQuery(cq);
  List<Tuple> result = q.getResultList();   

 对应 SQL:    SELECT name, COUNT(*) FROM employeeGROUP BY name HAVING name like 'N%'

 

查询投影

Criteria查询的结果与在Critiria查询创建中指定的一样。结果也能通过把查询根传入 CriteriaQuery.select中显式指定。Criteria查询也给开发者投影各种结果的能力。

 

使用construct()

使用该方法,查询结果能由非实体类型组成。在下面的代码片段中,为EmployeeDetail类创建了一个Criteria查询对象,而EmployeeDetail类并不是实体类型。

 

CriteriaQuery<EmployeeDetails> criteriaQuery = criteriaBuilder.createQuery(EmployeeDetails.class);
  Root<Employee> employee = criteriaQuery.from(Employee.class);
  criteriaQuery.select(criteriaBuilder.construct(EmployeeDetails.class, employee.get(Employee_.name), employee.get(Employee_.age)));
  em.createQuery(criteriaQuery).getResultList();
  Corresponding SQL: SELECT name, age FROM employee 

 

 

 

 

 返回Object[]的查询

Criteria查询也能通过设置值给CriteriaBuilder.array方法返回Object[]的结果。下面的代码片段中,数组大小是2(由StringInteger组成)。

 

CriteriaQuery<Object[]> criteriaQuery = criteriaBuilder.createQuery(Object[].class);
  Root<Employee> employee = criteriaQuery.from(Employee.class);
  criteriaQuery.select(criteriaBuilder.array(employee.get(Employee_.name), employee.get(Employee_.age)));
  em.createQuery(criteriaQuery).getResultList();

 

  对应 SQL: SELECT name, age FROM employee

 

返回元组(Tuple)的查询

数据库中的一行数据或单个记录通常称为元组。通过调用CriteriaBuilder.createTupleQuery()方法,查询可以用于元组上。CriteriaQuery.multiselect方法传入参数,它必须在查询中返回。

 

CriteriaQuery<Tuple> criteriaQuery = criteriaBuilder.createTupleQuery();
   Root<Employee> employee = criteriaQuery.from(Employee.class);
   criteriaQuery.multiselect(employee.get(Employee_.name).alias("name"), employee.get(Employee_.age).alias("age"));
   em.createQuery(criteriaQuery).getResultList();

 对应 SQL: SELECT name, age FROM employee

结论

     Criteria查询是一种以更加面向对象的方式查询数据库的方法、在本文中,我讨论了JPA2中类型安全的Criteria查询,以及对于理解Criteria查询非常重要的元模型的概念。也讨论了Criteria查询中的各种API

 

 

(完)

4
2
分享到:
评论
3 楼 hesai_vip 2014-03-03  
java.sql.SQLException: ORA-00979: 不是 GROUP BY 表达式

public static Specification<DfOperationCorrection> testDfoc(final Collection<Filter> filters) {
return new Specification<DfOperationCorrection>() {
@Override
public Predicate toPredicate(Root<DfOperationCorrection> root,
CriteriaQuery<?> query, CriteriaBuilder builder) {
Predicate pc = null;
root = query.from(DfOperationCorrection.class);
query.groupBy(root.get("applicationNo"));
pc = query.getGroupRestriction();

return pc;
}
};
}
2 楼 hesai_vip 2014-03-03  
mark一下。感觉使用分组.groupBy时无效。
1 楼 liuxiang00435057 2012-12-21  
我的分组统计是这样做的,但是红色部分不起作用
public List<Ulproduct> findAll(String username) {
List<Ulproduct> pageProducts = ulproductDao
.findAll(queryAllByMutiCondition(username));
return pageProducts;
}

private  Specification<Ulproduct> queryAllByMutiCondition(
final String username) {
return new Specification<Ulproduct>() {

@Override
public Predicate toPredicate(Root<Ulproduct> p,
CriteriaQuery<?> q, CriteriaBuilder cb) {
//q = cb.createQuery(Ulproduct.class);
p = q.from(Ulproduct.class);
q.groupBy(p.get("productsname"));

q.multiselect(p.<String>get("productsname"),
cb.sum(p.<Integer> get("stocksnum")),
cb.sum(p.<Double> get("price")),
cb.sum(p.<Double> get("cost")));


q.where(cb.equal(p.<String>get("username"),
StringUtils.trim(username)));

return q.getGroupRestriction();
}
};
}

相关推荐

    JPA核心知识总结

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

    jpa例子jpajpa

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

    Pro JPA 2版

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

    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 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的`...

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

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

    JPA连接数据库,非常详细

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

    SpringBoot+JPA.zip

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

    JPA-Hibernate包

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

    jpa

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

Global site tag (gtag.js) - Google Analytics