Criteria Api vs QueryDsl vs JPA metamodel

2022-09-04 21:03:37

我对这三个概念有点困惑。

  • 标准接口
  • Query Dsl
  • Jpa 2.0 元模型

根据我所读到的内容,使用QueryDsl或JPA元模型的主要好处之一是类型安全。
但是,即使使用标准 API,我也可以实现类型安全。(我正在使用JPA和eclipselink)

javax.persistence.EntityManager有两个变体

public Query createQuery(String sqlString);   
public <T> TypedQuery<T> createQuery(CriteriaQuery<T> criteriaQuery); 

我同意第一个版本,其中我将sql作为字符串传递,我没有得到类型安全。但是在第二个版本中,我获得了类型安全性。还是我在这里错过了什么?有人可以用一个例子来解释为什么使用标准不是类型安全的。

QueryDsl和JPA静态元模型有什么区别?


答案 1

JPA 提供三种基本类型的查询

  1. 用 JPQL 编写的查询。它具有TypedQueryNamedQuery的子类型。
  2. NativeQuery 用普通的 SQL 编写。
  3. 编程方式构造的条件 API 查询。它可以使用 Jpa 元模型来指定属性,使其更安全。

这些方法中的每一种都有自己的优点/缺点,因此您将根据自己的缺点选择一个。

QueryDSL是一个更简单,更直观(恕我直言)的库,可以替代JPA的Criteria API。


有问题的例子是TypedQuery。它只是Query的子类型,它在事先知道时定义返回类型,并删除可能的类型转换异常。它只是关于返回类型查询本身仍然是用普通的JPQL字符串构建的,所以它不是类型安全的查询。另一方面,Criteria API 是类型安全的。我们以编程方式生成查询,并且知道实体属性的类型。



具有部门关系的经典员工实体的示例

条件 Api 可以与基于字符串的属性一起使用。您可能会输入错误“部门”,然后得到错误。

Root<Employee> employee = query.from(Employee.class);
query.select(employee).where(cb.equal(employee.get("dept"), "HR"));

或者,我们可以使用 Jpa 元模型生成的元模型类来引用属性。您不能键入错误部门,因为您只能使用 Employee 中的现有属性名称。

Root<Employee> employee = query.from(Employee.class);
query.select(employee).where(cb.equal(employee.get(Employee_.dept), "HR"));

或者我们可以使用QueryDSL

QEmployee employee = QEmployee.employee;
query.from(employee).where(employee.dept.eq("HR"))

答案 2

您可以在 Criteria API 中使用 JPA 元模型来实现类型安全,但与 QueryDSL 相比,Criteria API 非常复杂


推荐