Spring Data JPA How to use Kotlin nulls instead of Optional
Solution 1
As of Spring Data Lovelace SR4 / Spring Boot 2.1.2, a CrudRepository.findByIdOrNull(id: ID): T? = findById(id).orElse(null)
Kotlin extension now provides out of the box a way to retrieve nullable entities in Spring Data.
If for performance reasons you would like to avoid the usage of Optional<T>
wrapper, be aware that you have also the possibility to create a custom interface with a findFooById(id: ID): T?
function. Query execution is store specific, but and most are using internally nullable values and will avoid the cost of Optional<T>
wrapper. Notice this overhead should be negligible for most use cases, so using the builtin extension is recommended method.
See DATACMNS-1346 for more details.
Solution 2
Update 12/2018:
An upcoming change in the Spring Data framework will make this answer obsolete. The update basically does the same as this answer: define an appropriate extension function. Please see Sébastien Deleuze's answer for further details.
Original answer:
As you correctly stated, you don't need Optional
in Kotlin, because handling nullability in a concise manner is a build in language feature.
You could create your own extension function to achieve the desired behaviour:
fun <T, ID> CrudRepository<T, ID>.findOne(id: ID): T? = findById(id).orElse(null)
and use it like this:
val fruit: Fruit? = fruitRepository.findOne(id)
Thanks to Giordano who showed me a way to make the function more concise.
Solution 3
Short version of Sébastien Deleuze's answer: Just define a function with a nullable return type:
interface UserRepository : Repository<User, String> {
// throws EmptyResultDataAccessException, if no user is found
fun findByUsername(username: String): User
// return null, if no user is found
fun findByFirstname(firstname: String?): User?
}
See Spring Data Reference Documentation.
CorayThan
Professional software developer and gamer. Check out my collectible card game website for KeyForge! https://decksofkeyforge.com/
Updated on June 17, 2022Comments
-
CorayThan almost 2 years
I'm writing a Spring Boot app with Spring Data JPA and Kotlin, and I've noticed that in
CrudRepository
there is the following method:Optional<T> findById(ID id);
I'm using Kotlin, though, which has much more fluent ways of dealing with nulls than
Optional
. Does anyone know how I would convert that method to work like this?fun findById(id: ID): T?
When I extend
Repository
itself and create a repo with that signature I get the error:java.lang.ClassCastException: java.util.Optional cannot be cast to com.books.Book
-
fast-reflexes almost 3 yearsA VERY important thing not to forget here is to make the ARGUMENT nullable also (like it is also in the example in the reference). Didn't do it and sat a good few hours trouble-shooting. It must have to do with that a
String
in Java can benull
(and thus corresponds to a nullableString?
in Kotlin) whereas along
in Java is primitive and can never benull
so it maps well withLong
in Kotlin... so it's all about helping the compiler map signatures! -
Renato Gama almost 3 yearsHow can I use this kotlin extension? Do I need to do anything special? I get unresolvedReference when trying to use I from a repo that extends
CrudRepository
-
Renato Gama almost 3 yearsNevermind, had to import it from
import org.springframework.data.repository.findByIdOrNull