存储库方法的 Null 处理

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

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

可为 Null 性注释

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

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

在 中声明不可为空package-info.java
@org.springframework.lang.NonNullApi
package com.acme;

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

以下示例显示了刚才描述的许多技术:spring-doc.cadn.net.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 The repository resides in a package (or sub-package) for which we have defined non-null behavior.
2 Throws an EmptyResultDataAccessException when the query does not produce a result. Throws an IllegalArgumentException when the emailAddress handed to the method is null.
3 Returns null when the query does not produce a result. Also accepts null as the value for emailAddress.
4 Returns Optional.empty() when the query does not produce a result. Throws an IllegalArgumentException when the emailAddress handed to the method is null.

Nullability in Kotlin-based Repositories

Kotlin has the definition of nullability constraints baked into the language. Kotlin code compiles to bytecode, which does not express nullability constraints through method signatures but rather through compiled-in metadata. Make sure to include the kotlin-reflect JAR in your project to enable introspection of Kotlin’s nullability constraints. Spring Data repositories use the language mechanism to define those constraints to apply the same runtime checks, as follows:spring-doc.cadn.net.cn

Using nullability constraints on Kotlin repositories
interface UserRepository : Repository<User, String> {

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

  fun findByFirstname(firstname: String?): User? (2)
}
1 The method defines both the parameter and the result as non-nullable (the Kotlin default). The Kotlin compiler rejects method invocations that pass null to the method. If the query yields an empty result, an EmptyResultDataAccessException is thrown.
2 This method accepts null for the firstname parameter and returns null if the query does not produce a result.