| 
 | 1 | +[[repositories.nullability]]  | 
 | 2 | +=== Null Handling of Repository Methods  | 
 | 3 | + | 
 | 4 | +As of Spring Data 2.0, repository CRUD methods that return an individual aggregate instance use Java 8's `Optional` to indicate the potential absence of a value.  | 
 | 5 | +Besides that, Spring Data supports returning the following wrapper types on query methods:  | 
 | 6 | + | 
 | 7 | +* `com.google.common.base.Optional`  | 
 | 8 | +* `scala.Option`  | 
 | 9 | +* `io.vavr.control.Option`  | 
 | 10 | + | 
 | 11 | +Alternatively, query methods can choose not to use a wrapper type at all.  | 
 | 12 | +The absence of a query result is then indicated by returning `null`.  | 
 | 13 | +Repository methods returning collections, collection alternatives, wrappers, and streams are guaranteed never to return `null` but rather the corresponding empty representation.  | 
 | 14 | +See "`<<repository-query-return-types>>`" for details.  | 
 | 15 | + | 
 | 16 | +[[repositories.nullability.annotations]]  | 
 | 17 | +==== Nullability Annotations  | 
 | 18 | + | 
 | 19 | +You can express nullability constraints for repository methods by using {spring-framework-docs}/core.html#null-safety[Spring Framework's nullability annotations].  | 
 | 20 | +They provide a tooling-friendly approach and opt-in `null` checks during runtime, as follows:  | 
 | 21 | + | 
 | 22 | +* {spring-framework-javadoc}/org/springframework/lang/NonNullApi.html[`@NonNullApi`]: Used on the package level to declare that the default behavior for parameters and return values is, respectively, neither to accept nor to produce `null` values.  | 
 | 23 | +* {spring-framework-javadoc}/org/springframework/lang/NonNull.html[`@NonNull`]: Used on a parameter or return value that must not be `null` (not needed on a parameter and return value where `@NonNullApi` applies).  | 
 | 24 | +* {spring-framework-javadoc}/org/springframework/lang/Nullable.html[`@Nullable`]: Used on a parameter or return value that can be `null`.  | 
 | 25 | + | 
 | 26 | +Spring annotations are meta-annotated with https://jcp.org/en/jsr/detail?id=305[JSR 305] annotations (a dormant but widely used JSR).  | 
 | 27 | +JSR 305 meta-annotations let tooling vendors (such as https://www.jetbrains.com/help/idea/nullable-and-notnull-annotations.html[IDEA], https://help.eclipse.org/latest/index.jsp?topic=/org.eclipse.jdt.doc.user/tasks/task-using_external_null_annotations.htm[Eclipse], and link:https://kotlinlang.org/docs/reference/java-interop.html#null-safety-and-platform-types[Kotlin]) provide null-safety support in a generic way, without having to hard-code support for Spring annotations.  | 
 | 28 | +To enable runtime checking of nullability constraints for query methods, you need to activate non-nullability on the package level by using Spring’s `@NonNullApi` in `package-info.java`, as shown in the following example:  | 
 | 29 | + | 
 | 30 | +.Declaring Non-nullability in `package-info.java`  | 
 | 31 | +====  | 
 | 32 | +[source,java]  | 
 | 33 | +----  | 
 | 34 | +@org.springframework.lang.NonNullApi  | 
 | 35 | +package com.acme;  | 
 | 36 | +----  | 
 | 37 | +====  | 
 | 38 | + | 
 | 39 | +Once non-null defaulting is in place, repository query method invocations get validated at runtime for nullability constraints.  | 
 | 40 | +If a query result violates the defined constraint, an exception is thrown.  | 
 | 41 | +This happens when the method would return `null` but is declared as non-nullable (the default with the annotation defined on the package in which the repository resides).  | 
 | 42 | +If you want to opt-in to nullable results again, selectively use `@Nullable` on individual methods.  | 
 | 43 | +Using the result wrapper types mentioned at the start of this section continues to work as expected: an empty result is translated into the value that represents absence.  | 
 | 44 | + | 
 | 45 | +The following example shows a number of the techniques just described:  | 
 | 46 | + | 
 | 47 | +.Using different nullability constraints  | 
 | 48 | +====  | 
 | 49 | +[source,java]  | 
 | 50 | +----  | 
 | 51 | +package com.acme;                                                       <1>  | 
 | 52 | +
  | 
 | 53 | +import org.springframework.lang.Nullable;  | 
 | 54 | +
  | 
 | 55 | +interface UserRepository extends Repository<User, Long> {  | 
 | 56 | +
  | 
 | 57 | +  User getByEmailAddress(EmailAddress emailAddress);                    <2>  | 
 | 58 | +
  | 
 | 59 | +  @Nullable  | 
 | 60 | +  User findByEmailAddress(@Nullable EmailAddress emailAdress);          <3>  | 
 | 61 | +
  | 
 | 62 | +  Optional<User> findOptionalByEmailAddress(EmailAddress emailAddress); <4>  | 
 | 63 | +}  | 
 | 64 | +----  | 
 | 65 | +<1> The repository resides in a package (or sub-package) for which we have defined non-null behavior.  | 
 | 66 | +<2> Throws an `EmptyResultDataAccessException` when the query does not produce a result.  | 
 | 67 | +Throws an `IllegalArgumentException` when the `emailAddress` handed to the method is `null`.  | 
 | 68 | +<3> Returns `null` when the query does not produce a result.  | 
 | 69 | +Also accepts `null` as the value for `emailAddress`.  | 
 | 70 | +<4> Returns `Optional.empty()` when the query does not produce a result.  | 
 | 71 | +Throws an `IllegalArgumentException` when the `emailAddress` handed to the method is `null`.  | 
 | 72 | +====  | 
 | 73 | + | 
 | 74 | +[[repositories.nullability.kotlin]]  | 
 | 75 | +==== Nullability in Kotlin-based Repositories  | 
 | 76 | + | 
 | 77 | +Kotlin has the definition of https://kotlinlang.org/docs/reference/null-safety.html[nullability constraints] baked into the language.  | 
 | 78 | +Kotlin code compiles to bytecode, which does not express nullability constraints through method signatures but rather through compiled-in metadata.  | 
 | 79 | +Make sure to include the `kotlin-reflect` JAR in your project to enable introspection of Kotlin's nullability constraints.  | 
 | 80 | +Spring Data repositories use the language mechanism to define those constraints to apply the same runtime checks, as follows:  | 
 | 81 | + | 
 | 82 | +.Using nullability constraints on Kotlin repositories  | 
 | 83 | +====  | 
 | 84 | +[source,kotlin]  | 
 | 85 | +----  | 
 | 86 | +interface UserRepository : Repository<User, String> {  | 
 | 87 | +
  | 
 | 88 | +  fun findByUsername(username: String): User     <1>  | 
 | 89 | +
  | 
 | 90 | +  fun findByFirstname(firstname: String?): User? <2>  | 
 | 91 | +}  | 
 | 92 | +----  | 
 | 93 | +<1> The method defines both the parameter and the result as non-nullable (the Kotlin default).  | 
 | 94 | +The Kotlin compiler rejects method invocations that pass `null` to the method.  | 
 | 95 | +If the query yields an empty result, an `EmptyResultDataAccessException` is thrown.  | 
 | 96 | +<2> This method accepts `null` for the `firstname` parameter and returns `null` if the query does not produce a result.  | 
 | 97 | +====  | 
0 commit comments