存储库方法的 Null 处理

从 Spring Data 2.0 开始,返回单个聚合实例的存储库 CRUD 方法使用 Java 8 来指示可能缺少值。 除此之外, Spring Data 支持在查询方法上返回以下包装器类型:Optionalspring-doc.cn

或者,查询方法可以选择根本不使用包装器类型。 然后,通过返回 来指示缺少查询结果。 返回集合、集合替代项、包装器和流的存储库方法保证永远不会返回,而是返回相应的空表示形式。 有关详细信息,请参阅“存储库查询返回类型”。nullnullspring-doc.cn

可为 Null 性注释

您可以使用 Spring Framework 的可为 null 性注释来表达存储库方法的可为 null 性约束。 它们提供了一种工具友好的方法,并在运行时提供选择加入检查,如下所示:nullspring-doc.cn

Spring 注解使用 JSR 305 注解(一种休眠但广泛使用的 JSR)进行元注解。 JSR 305 元注释允许工具供应商(例如 IDEAEclipseKotlin)以通用方式提供空安全支持,而不必对 Spring 注释进行硬编码支持。 要为查询方法启用可空性约束的运行时检查,您需要使用 Spring 的 in 在包级别激活非可空性,如以下示例所示:@NonNullApipackage-info.javaspring-doc.cn

在 中声明不可为空package-info.java

一旦非 null 默认值到位,存储库查询方法调用将在运行时验证是否为 null 性约束。 如果查询结果违反定义的约束,则会引发异常。 当方法返回但被声明为不可为空(在存储库所在的包上定义的注释的默认值)时,会发生这种情况。 如果要再次选择加入可为 null 的结果,请有选择地对单个方法使用。 使用本节开头提到的结果包装器类型将继续按预期工作:空结果将转换为表示 absence 的值。null@Nullablespring-doc.cn

以下示例显示了刚才描述的许多技术:spring-doc.cn

使用不同的可为 null 性约束
package com.acme;                                                       (1)

import org.springframework.lang.Nullable;

interface UserRepository extends Repository<User, Long> {

  User getByEmailAddress(EmailAddress emailAddress);                    (2)

  @Nullable
  User findByEmailAddress(@Nullable EmailAddress emailAdress);          (3)

  Optional<User> findOptionalByEmailAddress(EmailAddress emailAddress); (4)
}
1 存储库驻留在我们为其定义了非 null 行为的包(或子包)中。
2 当查询未生成结果时引发 an。 当传递给 method 的 为 时引发 an 。EmptyResultDataAccessExceptionIllegalArgumentExceptionemailAddressnull
3 当查询未生成结果时返回。 也接受作为 的值。nullnullemailAddress
4 当查询未生成结果时返回。 当传递给 method 的 为 时引发 an 。Optional.empty()IllegalArgumentExceptionemailAddressnull

基于 Kotlin 的存储库中的 Null 性

Kotlin 将可为 null 性约束的定义融入到语言中。 Kotlin 代码编译为字节码,字节码不通过方法签名来表示可为 null 性约束,而是通过编译的元数据来表示。 确保在项目中包含 JAR,以便能够内省 Kotlin 的可为 null 性约束。 Spring Data 存储库使用语言机制来定义这些约束以应用相同的运行时检查,如下所示:kotlin-reflectspring-doc.cn

在 Kotlin 代码库上使用可为 null 性约束
interface UserRepository : Repository<User, String> {

  fun findByUsername(username: String): User     (1)

  fun findByFirstname(firstname: String?): User? (2)
}
1 该方法将参数和结果定义为不可为 null(Kotlin 默认值)。 Kotlin 编译器拒绝传递给该方法的方法调用。 如果查询产生空结果,则抛出 an。nullEmptyResultDataAccessException
2 此方法接受参数,如果查询未生成结果,则返回。nullfirstnamenull