Spring Data JPA Repository中的派生查询方法

2023/05/18

1. 概述

对于简单的查询,只需查看我们代码中相应的方法名称,就可以很容易地得出查询应该是什么

在本教程中,我们将探讨Spring Data JPA如何以方法命名约定的形式利用这一想法。

Spring Data JPA简介

Spring Data JPA与Spring 4简介-Spring配置、DAO、手动和生成的查询以及事务管理。

阅读更多

Spring Data中的CrudRepository、JpaRepository和PagingAndSortingRepository

了解Spring Data提供的不同风格的Repository。

阅读更多

使用Spring Data对查询结果进行排序

了解在Spring Data查询中对结果进行排序的不同方法。

阅读更多

2. Spring派生查询方法结构

派生方法名称有两个主要部分,由第一个By关键字分隔

List<User> findByName(String name)

第一部分(例如find)是动词,其余部分(例如ByName)是标准。

Spring Data JPA支持find、read、query、count和get。因此,我们可以使用queryByName,Spring Data的行为也是一样的。

我们还可以使用Distinct、First或Top来删除重复项或限制我们的结果集:

List<User> findTop3ByAge()

条件部分包含查询的特定于实体的条件表达式。我们可以将条件关键字与实体的属性名称一起使用。

我们还可以使用And和Or将表达式连接起来,稍后我们将看到。

3. 示例应用程序

首先,我们需要构建一个Spring Data JPA的应用程序。

在该应用程序中,让我们定义一个实体类:

@Table(name = "users")
@Entity
public class User {

    @Id
    @GeneratedValue
    private Integer id;
    private String name;
    private Integer age;
    private ZonedDateTime birthDate;
    private Boolean active;
    // standard getters and setters ...
}

我们还需要定义一个Repository。它将扩展JpaRepository,这是Spring Data Repository类型之一:

public interface UserRepository extends JpaRepository<User, Integer> {
}

我们将在该接口中定义所有派生查询方法。

4. Equals条件关键字

完全相等是查询中最常用的条件之一。我们有几个选项可以在查询中表达“=”或“IS”运算符。

对于完全匹配条件,我们可以只附加不带任何关键字的属性名称:

List<User> findByName(String name);

为了提高可读性,我们可以添加Is或Equals关键字:

List<User> findByNameIs(String name);
List<User> findByNameEquals(String name);

当我们需要表达不等式时,这种额外的可读性会派上用场:

List<User> findByNameIsNot(String name);

这比findByNameNot(String)更具可读性。

由于null相等是一种特殊情况,我们不应该使用“=”运算符。Spring Data JPA默认处理null参数。因此,当我们为相等条件传递空值时,Spring会在生成的SQL中将查询解释为IS NULL。

我们还可以使用IsNull关键字将IS NULL条件添加到查询中:

List<User> findByNameIsNull();
List<User> findByNameIsNotNull();

请注意,IsNull和IsNotNull都不需要声明方法参数。

还有另外两个不需要任何参数的关键字。

我们可以使用True和False关键字为布尔类型添加相等条件:

List<User> findByActiveTrue();
List<User> findByActiveFalse();

5. 相似条件关键字

当我们需要使用属性模式查询结果时,我们有几个选择。

我们可以使用StartingWith查找以某个值开头的name:

List<User> findByNameStartingWith(String prefix);

粗略地说,这个方法被解释为WHERE name LIKE ‘value%’。

如果我们想要以给定值结尾的名称,则可以使用EndingWith:

List<User> findByNameEndingWith(String suffix);

或者我们可以通过Containing找到哪些名称包含一个值:

List<User> findByNameContaining(String infix);

请注意,上述所有条件都称为预定义模式表达式。因此,调用这些方法时,我们不需要在参数中添加“%”运算符

但是假设我们正在做一些更复杂的事情。假设我们需要获取名称以a开头、包含b并以c结尾的用户。

为此,我们可以使用Like关键字添加自己的LIKE条件:

List<User> findByNameLike(String likePattern);

然后我们可以在调用方法时传递我们的LIKE条件:

String likePattern = "a%b%c";
userRepository.findByNameLike(likePattern);

6. 比较条件关键字

此外,我们可以使用LessThan和LessThanEqual关键字来使用”<“和”<=“运算符将记录与给定值进行比较:

List<User> findByAgeLessThan(Integer age);
List<User> findByAgeLessThanEqual(Integer age);

在相反的情况下,我们可以使用GreaterThan和GreaterThanEqual关键字:

List<User> findByAgeGreaterThan(Integer age);
List<User> findByAgeGreaterThanEqual(Integer age);

或者我们可以找到两个年龄段之间的用户:

List<User> findByAgeBetween(Integer startAge, Integer endAge);

我们还可以提供一个包含age值的集合,以匹配年龄在集合中的用户:

List<User> findByAgeIn(Collection<Integer> ages);

因为我们知道用户的生日,所以我们可能想要查询出生在给定日期之前或之后的用户。

为此,我们将使用Before和After:

List<User> findByBirthDateAfter(ZonedDateTime birthDate);
List<User> findByBirthDateBefore(ZonedDateTime birthDate);

7. 多条件表达式

我们可以通过使用And和Or关键字来组合任意数量的表达式:

List<User> findByNameOrBirthDate(String name, ZonedDateTime birthDate);
List<User> findByNameOrBirthDateAndActive(String name, ZonedDateTime birthDate, Boolean active);

优先顺序是And,然后是Or,就像Java一样。

虽然Spring Data JPA对我们可以添加的表达式数量没有限制,但我们不应该无限制地组合多个条件。长名称的方法名难以阅读且难以维护。对于复杂的查询,请改为查看@Query注解

8. 排序结果

接下来,让我们看一下排序。

我们可以使用OrderBy按姓名的字母顺序对用户进行排序:

List<User> findByNameOrderByName(String name);
List<User> findByNameOrderByNameAsc(String name);

升序是默认的排序方式,但我们可以使用Desc进行降序排序:

List<User> findByNameOrderByNameDesc(String name);

9. CurdRepository中的findOne和findById比较

Spring团队在Spring Boot 2.x的CrudRepository中做了一些重大更改。其中之一是将findOne重命名为findById。

以前使用Spring Boot 1.x时,当我们想通过主键检索实体时,我们会调用findOne:

User user = userRepository.findOne(1);

从Spring Boot 2.X开始,我们可以用findById()进行同样的操作:

User user = userRepository.findById(1);

请注意,findById()方法已经在CrudRepository中为我们定义。因此,我们不必在扩展CrudRepository的自定义Repository中明确定义它。

10. 总结

在本文中,我们解释了Spring Data JPA中的查询派生机制。我们使用属性条件关键字在Spring Data JPA Repository中编写派生查询方法。

与往常一样,本教程的完整源代码可在GitHub上获得。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章