Criteria API 简介

在 Hibernate 中有两种写数据库查询的方法:

  • 休眠查询语言
  • 标准API

您很久以前就已经遇到过第一个,是时候熟悉 Criteria API 了。这是一个非常强大的工具,在某些时候它甚至比 HQL 更受欢迎。现在它不再那么流行了,但对于某些任务来说,它肯定是比 HQL 更好的解决方案。

无论如何,不​​熟悉 Criteria API 就无法学习 Hibernate。我们先写一个小例子,然后我们来分析。例如,我们会从数据库中请求所有员工(Employee)。这是我们将得到的:

CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Employee> critQuery = builder.createQuery(Employee.class);

Root<Employee> root = critQuery.from(Employee.class);
critQuery.select(root);

Query<Employee> query = session.createQuery(critQuery);
List<Employee> results = query.getResultList();

看起来很复杂。让我们编写相同的 HQL 查询进行比较:

String hqlQuery = "from Employee";

Query<Employee> query = session.createQuery(hqlQuery);
List<Employee> results = query.getResultList();

请注意,两个示例的最后两行几乎相同:我们创建了一个 Query 对象并使用它来获取一个 List。这暗示其余的行正在做相同的事情。

查看第一个示例的第 3 行和第 4 行:

Root<Employee> root = critQuery.from(Employee.class);
critQuery.select(root);

让我们把它们写成一行:

critQuery.select(critQuery.from(Employee.class));

是不是让你想起了什么?如果你给它涂上一点不同的颜色:

critQuery.select(critQuery.from(Employee.class));

是的,这是一个非常棘手的 SELECT FROM 查询结构。

使用 Criteria API 的示例

为了更好地理解,我将仅举几个例子。

请求 1。获取所有工资在1万以上的员工:

critQuery.select(critQuery.from(Employee.class)).where(builder.gt(root.get("salary"), 10000));

请求 2。获取所有工资低于5万的员工:

critQuery.select(critQuery.from(Employee.class)).where(builder.lt(root.get("salary"), 50000));

请求 3。获取职位名称中包含单词“test”的所有员工:

critQuery.select(critQuery.from(Employee.class)).where(builder.like(root.get("occupation"), "%test%"));

请求 4。获取工资在10到5万之间的所有员工:

critQuery.select(critQuery.from(Employee.class)).where(builder.between(root.get("salary"), 10000, 50000));

请求 5。获取名称为空的所有员工:

critQuery.select(critQuery.from(Employee.class)).where(builder.isNull(root.get("name")));

请求 6。获取名称不为空的所有员工:

critQuery.select(critQuery.from(Employee.class)).where(builder.isNotNull(root.get("name")));

这是构建查询的一种非常棘手的方法:

  • 首先你得到对象标准生成器.
  • 然后用它来创建一个对象条件查询.
  • 然后你开始向它添加零件条件查询标准生成器.

您可以通过以下方式设置参数:

  • 选择
  • 在哪里

同时使用标准生成器您可以为 WHERE 构建不同的条件。

使用 Criteria API 的高级工作

使用 Criteria API,您可以构建任何复杂性的查询。这是个好消息。例如,您需要一个复杂的 WHERE 子句。方法如下:

Predicate greaterThan = builder.gt(root.get("salary"), 1000);
Predicate testers = builder.like(root.get("occupation"), "test%");

critQuery.select(critQuery.from(Employee.class)).where(builder.or(greaterThan, testers));

如果你想写AND而不是OR,那么你只需要改变最后一行:

critQuery.select(critQuery.from(Employee.class)).where(builder.and(greaterThan, testers));

一切其实都很简单。让我给你一个表格和一些比较:

数据库 方法 全记录
一个<乙 lt(a, b) builder.lt(a, b)
一个 > 乙 GT(a, b) builder.gt(a,b)
或(一,二) 建造者或(a,b)
一个和b 和(一,二) 建造者和(a,b)
喜欢b 喜欢(a,b) builder.like(a,b)
(c, d) 之间 在(a,c,d)之间 builder.between(a, c, d)
一个是空的 isNull(a) builder.isNull(a)
不为空 isNotNull(a) builder.isNotNull(a)

一切都很简单,不是吗?

我们如何向查询添加排序?很简单的:

critQuery.select( critQuery.from(Employee.class) );
critQuery.where( builder.and(greaterThan, testers) );
critQuery.orderBy( builder.asc(root.get("salary"), builder.desc(root.get("joinDate") )

您只需调用该对象条件查询orderBy()方法并将所需的参数传递给它。

下面是相同查询在 HQL 中的样子。比较:

select * from Employee
where (…) and (…)
order by 'salary' asc, 'joinDate' desc

你只需要记住三件事:

  • 在对象上调用 SELECT、FROM、WHERE 等关键运算符条件查询.
  • 在对象上调用 AND、OR、DESC 等辅助运算符标准生成器.
  • 字段名称通过get()从对象中获取.