Spring Data JPA如何使用Kotlin nulls而不是Optional

Cor*_*han 23 java spring-data-jpa kotlin spring-boot

我正在用Spring Data JPA和Kotlin编写Spring Boot应用程序,我注意到CrudRepository有以下方法:

Optional<T> findById(ID id);
Run Code Online (Sandbox Code Playgroud)

不过,我正在使用Kotlin,它有更流畅的处理空值的方法Optional.有谁知道如何将这种方法转换成这样的工作?

fun findById(id: ID): T?
Run Code Online (Sandbox Code Playgroud)

当我扩展Repository自己并使用该签名创建一个repo时,我得到错误:

java.lang.ClassCastException: java.util.Optional cannot be cast to com.books.Book
Run Code Online (Sandbox Code Playgroud)

Séb*_*uze 35

从Spring Data Lovelace SR4/Spring Boot 2.1.2开始,CrudRepository.findByIdOrNull(id: ID): T? = findById(id).orElse(null)Kotlin扩展现在提供了一种在Spring Data中检索可空实体的方法.

如果出于性能原因,您希望避免使用Optional<T>包装器,请注意您还可以使用findFooById(id: ID): T?函数创建自定义接口.查询执行是特定于商店的,但大多数都使用内部可为空的值,并且将避免Optional<T>包装的成本.请注意,对于大多数用例,此开销应该可以忽略不计,因此建议使用内置扩展.

有关详细信息,请参阅DATACMNS-1346.


Wil*_*zel 16

更新12/2018:

Spring Data框架即将发生的变化将使这个答案过时.更新基本上与此答案相同:定义适当的扩展功能.有关详细信息,请参阅SébastienDeleuze的答案.

原始答案:

正如你所说,你Optional在Kotlin中不需要,因为以简洁的方式处理可空性是一种语言特性.

您可以创建自己的扩展函数来实现所需的行为:

fun <T, ID> CrudRepository<T, ID>.findOne(id: ID): T? = findById(id).orElse(null)
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:

val fruit: Fruit? = fruitRepository.findOne(id)
Run Code Online (Sandbox Code Playgroud)

感谢Giordano向我展示了一种使功能更简洁的方法.


dea*_*mon 6

S\xc3\xa9bastien Deleuze\ 的答案的简短版本:只需定义一个具有可为空返回类型的函数

\n\n
interface UserRepository : Repository<User, String> {\n\n  // throws EmptyResultDataAccessException, if no user is found\n  fun findByUsername(username: String): User     \n\n  // return null, if no user is found\n  fun findByFirstname(firstname: String?): User? \n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

请参阅 Spring Data 参考文档

\n

  • 这里不要忘记的一件非常重要的事情是使 ARGUMENT 也可以为空(就像参考文献中的示例一样)。我没有这么做,而是花了好几个小时来排除故障。这一定与 Java 中的“String”可以为“null”有关(因此对应于 Kotlin 中可空的“String?”),而 Java 中的“long”是原始类型,永远不能为“null”,因此它与 Kotlin 中的“Long”很好地映射...所以这一切都是为了帮助编译器映射签名! (2认同)