通常在存储库上触发的大多数数据访问操作都会导致对数据库运行查询。 定义这样的查询是在存储库接口上声明方法的问题,如以下示例所示:Spring中文文档

例 1.具有查询方法的 PersonRepository
interface ReactivePersonRepository extends ReactiveSortingRepository<Person, Long> {

  Flux<Person> findByFirstname(String firstname);                                   (1)

  Flux<Person> findByFirstname(Publisher<String> firstname);                        (2)

  Flux<Person> findByFirstnameOrderByLastname(String firstname, Pageable pageable); (3)

  Mono<Person> findByFirstnameAndLastname(String firstname, String lastname);       (4)

  Mono<Person> findFirstByLastname(String lastname);                                (5)

  @Query("SELECT * FROM person WHERE lastname = :lastname")
  Flux<Person> findByLastname(String lastname);                                     (6)

  @Query("SELECT firstname, lastname FROM person WHERE lastname = $1")
  Mono<Person> findFirstByLastname(String lastname);                                (7)
}
1 该方法显示对具有给定 . 通过分析可与 和 连接的约束的方法名称来派生查询。 因此,方法名称将生成 .firstnameAndOrSELECT … FROM person WHERE firstname = :firstname
2 该方法显示对所有具有给定的人的查询,一旦给定 发出 。firstnamefirstnamePublisher
3 用于将偏移量和排序参数传递到数据库。Pageable
4 查找给定条件的单个实体。 它以非唯一结果完成。IncorrectResultSizeDataAccessException
5 除非 <4>,否则即使查询生成更多结果行,也始终发出第一个实体。
6 该方法显示对具有给定姓氏的所有人员的查询。findByLastname
7 对仅投影和列的单个实体的查询。 带批注的查询使用本机绑定标记,在此示例中,这些标记是 Postgres 绑定标记。Personfirstnamelastname

请注意,批注中使用的 select 语句的列必须与 for 相应属性生成的名称匹配。 如果 select 语句不包含匹配列,则不会设置该属性。 如果持久性构造函数需要该属性,则提供 null 或(对于基元类型)默认值。@QueryNamingStrategySpring中文文档

下表显示了查询方法支持的关键字:Spring中文文档

表 1.查询方法支持的关键字
关键词 样本 合乎逻辑的结果

AfterSpring中文文档

findByBirthdateAfter(Date date)Spring中文文档

birthdate > dateSpring中文文档

GreaterThanSpring中文文档

findByAgeGreaterThan(int age)Spring中文文档

age > ageSpring中文文档

GreaterThanEqualSpring中文文档

findByAgeGreaterThanEqual(int age)Spring中文文档

age >= ageSpring中文文档

BeforeSpring中文文档

findByBirthdateBefore(Date date)Spring中文文档

birthdate < dateSpring中文文档

LessThanSpring中文文档

findByAgeLessThan(int age)Spring中文文档

age < ageSpring中文文档

LessThanEqualSpring中文文档

findByAgeLessThanEqual(int age)Spring中文文档

age <= ageSpring中文文档

BetweenSpring中文文档

findByAgeBetween(int from, int to)Spring中文文档

age BETWEEN from AND toSpring中文文档

NotBetweenSpring中文文档

findByAgeNotBetween(int from, int to)Spring中文文档

age NOT BETWEEN from AND toSpring中文文档

InSpring中文文档

findByAgeIn(Collection<Integer> ages)Spring中文文档

age IN (age1, age2, ageN)Spring中文文档

NotInSpring中文文档

findByAgeNotIn(Collection ages)Spring中文文档

age NOT IN (age1, age2, ageN)Spring中文文档

IsNotNull,NotNullSpring中文文档

findByFirstnameNotNull()Spring中文文档

firstname IS NOT NULLSpring中文文档

IsNull,NullSpring中文文档

findByFirstnameNull()Spring中文文档

firstname IS NULLSpring中文文档

Like, ,StartingWithEndingWithSpring中文文档

findByFirstnameLike(String name)Spring中文文档

firstname LIKE nameSpring中文文档

NotLike,IsNotLikeSpring中文文档

findByFirstnameNotLike(String name)Spring中文文档

firstname NOT LIKE nameSpring中文文档

Containing在字符串上Spring中文文档

findByFirstnameContaining(String name)Spring中文文档

firstname LIKE '%' + name +'%'Spring中文文档

NotContaining在字符串上Spring中文文档

findByFirstnameNotContaining(String name)Spring中文文档

firstname NOT LIKE '%' + name +'%'Spring中文文档

(No keyword)Spring中文文档

findByFirstname(String name)Spring中文文档

firstname = nameSpring中文文档

NotSpring中文文档

findByFirstnameNot(String name)Spring中文文档

firstname != nameSpring中文文档

IsTrue,TrueSpring中文文档

findByActiveIsTrue()Spring中文文档

active IS TRUESpring中文文档

IsFalse,FalseSpring中文文档

findByActiveIsFalse()Spring中文文档

active IS FALSESpring中文文档

1 该方法显示对具有给定 . 通过分析可与 和 连接的约束的方法名称来派生查询。 因此,方法名称将生成 .firstnameAndOrSELECT … FROM person WHERE firstname = :firstname
2 该方法显示对所有具有给定的人的查询,一旦给定 发出 。firstnamefirstnamePublisher
3 用于将偏移量和排序参数传递到数据库。Pageable
4 查找给定条件的单个实体。 它以非唯一结果完成。IncorrectResultSizeDataAccessException
5 除非 <4>,否则即使查询生成更多结果行,也始终发出第一个实体。
6 该方法显示对具有给定姓氏的所有人员的查询。findByLastname
7 对仅投影和列的单个实体的查询。 带批注的查询使用本机绑定标记,在此示例中,这些标记是 Postgres 绑定标记。Personfirstnamelastname
表 1.查询方法支持的关键字
关键词 样本 合乎逻辑的结果

AfterSpring中文文档

findByBirthdateAfter(Date date)Spring中文文档

birthdate > dateSpring中文文档

GreaterThanSpring中文文档

findByAgeGreaterThan(int age)Spring中文文档

age > ageSpring中文文档

GreaterThanEqualSpring中文文档

findByAgeGreaterThanEqual(int age)Spring中文文档

age >= ageSpring中文文档

BeforeSpring中文文档

findByBirthdateBefore(Date date)Spring中文文档

birthdate < dateSpring中文文档

LessThanSpring中文文档

findByAgeLessThan(int age)Spring中文文档

age < ageSpring中文文档

LessThanEqualSpring中文文档

findByAgeLessThanEqual(int age)Spring中文文档

age <= ageSpring中文文档

BetweenSpring中文文档

findByAgeBetween(int from, int to)Spring中文文档

age BETWEEN from AND toSpring中文文档

NotBetweenSpring中文文档

findByAgeNotBetween(int from, int to)Spring中文文档

age NOT BETWEEN from AND toSpring中文文档

InSpring中文文档

findByAgeIn(Collection<Integer> ages)Spring中文文档

age IN (age1, age2, ageN)Spring中文文档

NotInSpring中文文档

findByAgeNotIn(Collection ages)Spring中文文档

age NOT IN (age1, age2, ageN)Spring中文文档

IsNotNull,NotNullSpring中文文档

findByFirstnameNotNull()Spring中文文档

firstname IS NOT NULLSpring中文文档

IsNull,NullSpring中文文档

findByFirstnameNull()Spring中文文档

firstname IS NULLSpring中文文档

Like, ,StartingWithEndingWithSpring中文文档

findByFirstnameLike(String name)Spring中文文档

firstname LIKE nameSpring中文文档

NotLike,IsNotLikeSpring中文文档

findByFirstnameNotLike(String name)Spring中文文档

firstname NOT LIKE nameSpring中文文档

Containing在字符串上Spring中文文档

findByFirstnameContaining(String name)Spring中文文档

firstname LIKE '%' + name +'%'Spring中文文档

NotContaining在字符串上Spring中文文档

findByFirstnameNotContaining(String name)Spring中文文档

firstname NOT LIKE '%' + name +'%'Spring中文文档

(No keyword)Spring中文文档

findByFirstname(String name)Spring中文文档

firstname = nameSpring中文文档

NotSpring中文文档

findByFirstnameNot(String name)Spring中文文档

firstname != nameSpring中文文档

IsTrue,TrueSpring中文文档

findByActiveIsTrue()Spring中文文档

active IS TRUESpring中文文档

IsFalse,FalseSpring中文文档

findByActiveIsFalse()Spring中文文档

active IS FALSESpring中文文档

修改查询

前面的部分介绍如何声明查询以访问给定实体或实体集合。 使用上表中的关键字可以与删除匹配行的派生查询结合使用,也可以用于创建派生查询。delete…Byremove…BySpring中文文档

例 2. 查询Delete…By
interface ReactivePersonRepository extends ReactiveSortingRepository<Person, String> {

  Mono<Integer> deleteByLastname(String lastname);            (1)

  Mono<Void> deletePersonByLastname(String lastname);         (2)

  Mono<Boolean> deletePersonByLastname(String lastname);      (3)
}
1 使用 return type of 返回受影响的行数。Mono<Integer>
2 仅使用报告行是否已成功删除,而不发出结果值。Void
3 使用报告是否至少删除了一行。Boolean

由于此方法对于全面的自定义功能是可行的,因此可以通过使用 批注查询方法来修改只需要参数绑定的查询,如以下示例所示:@ModifyingSpring中文文档

@Modifying
@Query("UPDATE person SET firstname = :firstname where lastname = :lastname")
Mono<Integer> setFixedFirstnameFor(String firstname, String lastname);

修改查询的结果可以是:Spring中文文档

注释仅与注释结合使用。 派生的自定义方法不需要此批注。@Modifying@QuerySpring中文文档

修改查询是直接针对数据库执行的。 不会调用任何事件或回调。 因此,如果具有审核批注的字段未在批注查询中更新,则这些字段也不会更新。Spring中文文档

或者,您可以使用 Spring 数据存储库的自定义实现中描述的功能添加自定义修改行为。Spring中文文档

1 使用 return type of 返回受影响的行数。Mono<Integer>
2 仅使用报告行是否已成功删除,而不发出结果值。Void
3 使用报告是否至少删除了一行。Boolean

@Query

下面的示例演示如何使用声明查询方法:@QuerySpring中文文档

使用 @Query 声明查询方法
interface UserRepository extends ReactiveCrudRepository<User, Long> {

  @Query("select firstName, lastName from User u where u.emailAddress = :email")
  Flux<User> findByEmailAddress(@Param("email") String email);
}
请注意,基于字符串的查询不支持分页,也不接受 、 ,并且作为查询参数,对于这些查询,需要重写查询。 如果要应用限制,请使用 SQL 表达此意图,并自行将相应的参数绑定到查询。SortPageRequestLimit
Spring 完全支持 Java 8 基于编译器标志的参数名称发现。 通过在生成中使用此标志作为调试信息的替代方法,可以省略命名参数的批注。-parameters@Param

使用 SpEL 表达式进行查询

查询字符串定义可以与 SpEL 表达式一起使用,以在运行时创建动态查询。 SpEL 表达式可以提供谓词值,这些值在运行查询之前进行计算。Spring中文文档

表达式通过包含所有参数的数组公开方法参数。 以下查询用于声明 (等效于参数绑定) 的谓词值:[0]lastname:lastnameSpring中文文档

@Query("SELECT * FROM person WHERE lastname = :#{[0]}")
Flux<Person> findByQueryWithExpression(String lastname);

查询字符串中的 SpEL 是增强查询的有效方法。 但是,他们也可以接受各种不需要的论点。 应确保在将字符串传递给查询之前对其进行清理,以避免对查询进行不必要的更改。Spring中文文档

表达式支持可通过查询 SPI 进行扩展: 。 查询 SPI 可以提供属性和函数,并可以自定义根对象。 在生成查询时,在 SpEL 评估时从应用程序上下文中检索扩展。org.springframework.data.spel.spi.EvaluationContextExtensionSpring中文文档

将 SpEL 表达式与纯参数结合使用时,请使用命名参数表示法而不是本机绑定标记,以确保正确的绑定顺序。
请注意,基于字符串的查询不支持分页,也不接受 、 ,并且作为查询参数,对于这些查询,需要重写查询。 如果要应用限制,请使用 SQL 表达此意图,并自行将相应的参数绑定到查询。SortPageRequestLimit
Spring 完全支持 Java 8 基于编译器标志的参数名称发现。 通过在生成中使用此标志作为调试信息的替代方法,可以省略命名参数的批注。-parameters@Param
将 SpEL 表达式与纯参数结合使用时,请使用命名参数表示法而不是本机绑定标记,以确保正确的绑定顺序。