Spring Data JPA How to use Kotlin nulls instead of

2019-02-08 13:02发布

问题:

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

回答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.



回答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.