Criteria API – An Example of IN Expressions – Criteria API – IN表达式的一个例子

最后修改: 2018年 11月 18日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

We often come across problems where we need to query entities based on whether a single-valued attribute is a member of a given collection.

我们经常遇到这样的问题:我们需要根据一个单值属性是否是某个集合的成员来查询实体。

In this tutorial, we’ll learn how to solve this problem with the help of the Criteria API.

在本教程中,我们将学习如何在Criteria API的帮助下解决这个问题。

2. Sample Entities

2.实体样本

Before we start, let’s take a look at the entities that we’re going to use in our write-up.

在我们开始之前,让我们看一下我们将在写作中使用的实体。

We have a DeptEmployee class that has a many-to-one relationship with a Department class:

我们有一个DeptEmployee类,它与Department类有many-to-one关系

@Entity
public class DeptEmployee {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private long id;

    private String title;

    @ManyToOne
    private Department department;
}

Also, the Department entity that maps to multiple DeptEmployees:

还有,映射到多个DeptEmployeesDepartment实体。

@Entity
public class Department {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private long id;

    private String name;

    @OneToMany(mappedBy="department")
    private List<DeptEmployee> employees;
}

3. The CriteriaBuilder.In

3.CriteriaBuilder.In

First of all, let’s use the CriteriaBuilder interface. The in() method accepts an Expression and returns a new Predicate of the CriteriaBuilder.In type. It can be used to test whether the given expression is contained in the list of values:

首先,让我们使用CriteriaBuilder接口。in()方法接受一个Expression,并返回一个CriteriaBuilder.In类型的新的Predicate它可以用来测试给定的表达式是否包含在值的列表中。

CriteriaQuery<DeptEmployee> criteriaQuery = 
  criteriaBuilder.createQuery(DeptEmployee.class);
Root<DeptEmployee> root = criteriaQuery.from(DeptEmployee.class);
In<String> inClause = criteriaBuilder.in(root.get("title"));
for (String title : titles) {
    inClause.value(title);
}
criteriaQuery.select(root).where(inClause);

4. The Expression.In

4.Expression.In

Alternatively, we can use a set of overloaded in() methods from the Expression interface:

另外,我们可以使用Expression接口中的一组重载in()方法。

criteriaQuery.select(root)
  .where(root.get("title")
  .in(titles));

In a contrast to the CriteriaBuilder.in(), the Expression.in() accepts a collection of values. As we can see it also simplifies our code a little bit.

CriteriaBuilder.in()相比,Expression.in()接受一个值的集合。正如我们所见,它也稍微简化了我们的代码。

5. IN Expressions Using Subqueries

5.使用子查询的IN表达式

So far, we have used collections with predefined values. Now, let’s take a look at an example when a collection is derived from an output of a subquery.

到目前为止,我们已经使用了具有预定义值的集合。现在,让我们来看看一个例子,当一个集合从一个子查询的输出中派生出来时。

For instance, we can fetch all DeptEmployees who belong to a Department, with the specified keyword in their name:

例如,我们可以获取属于某个部门的所有DeptEmployees,其名称中含有指定的关键字。

Subquery<Department> subquery = criteriaQuery.subquery(Department.class);
Root<Department> dept = subquery.from(Department.class);
subquery.select(dept)
  .distinct(true)
  .where(criteriaBuilder.like(dept.get("name"), "%" + searchKey + "%"));

criteriaQuery.select(emp)
  .where(criteriaBuilder.in(emp.get("department")).value(subquery));

Here, we created a subquery that was then passed into the value() as an expression to search for the Department entity.

在这里,我们创建了一个子查询,然后作为一个表达式传入value(),以搜索Department实体。

6. Conclusion

6.结语

In this quick article, we have learned different ways to achieve the IN operation using the Criteria API. We have also explored how to use the Criteria API with subqueries.

在这篇快速文章中,我们学习了使用Criteria API实现IN操作的不同方法。我们还探讨了如何使用子查询的标准API。

Finally, the complete implementation for this tutorial is available on GitHub.

最后,本教程的完整实现是在GitHub上提供的