【问题标题】:Spring Data JPA How to use Kotlin nulls instead of OptionalSpring Data JPA 如何使用 Kotlin nulls 而不是 Optional
【发布时间】:2018-04-18 23:32:36
【问题描述】:

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

Optional<T> findById(ID id);

不过,我使用的是 Kotlin,它处理空值的方式比 Optional 更流畅。有谁知道我将如何将该方法转换为这样工作?

fun findById(id: ID): T?

当我扩展 Repository 本身并使用该签名创建一个 repo 时,我收到错误:

java.lang.ClassCastException: java.util.Optional cannot be cast to com.books.Book

【问题讨论】:

    标签: java spring-boot kotlin spring-data-jpa


    【解决方案1】:

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

    如果出于性能原因您想避免使用Optional&lt;T&gt; 包装器,请注意您也可以使用findFooById(id: ID): T? 函数创建自定义接口。查询执行是特定于存储的,但大多数都使用内部可为空的值,并将避免 Optional&lt;T&gt; 包装器的成本。请注意,对于大多数用例来说,这种开销应该可以忽略不计,因此建议使用内置扩展。

    更多详情请见DATACMNS-1346

    【讨论】:

    • 如何使用这个 kotlin 扩展?我需要做一些特别的事情吗?尝试从扩展 CrudRepository 的存储库中使用 I 时,我得到 unresolvedReference
    • 没关系,必须从import org.springframework.data.repository.findByIdOrNull导入它
    【解决方案2】:

    2018 年 12 月更新:

    Spring Data 框架即将发生的变化将使这个答案过时。更新基本上与此答案相同:定义适当的扩展功能。详情请见Sébastien Deleuze's answer

    原答案:

    正如您所说的那样,在 Kotlin 中您不需要 Optional,因为以简洁的方式处理可空性是语言的内置功能。

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

    fun <T, ID> CrudRepository<T, ID>.findOne(id: ID): T? = findById(id).orElse(null)
    

    并像这样使用它:

    val fruit: Fruit? = fruitRepository.findOne(id)
    

    感谢Giordano,他向我展示了一种使函数更简洁的方法。

    【讨论】:

      【解决方案3】:

      Sébastien Deleuze's answer 的短版:只需定义一个 返回类型可以为空的函数

      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? 
      }
      

      请参阅 Spring 数据参考 Documentation

      【讨论】:

      • 这里不要忘记的一个非常重要的事情是使 ARGUMENT 也可以为空(就像它也在参考中的示例中一样)。没有这样做,坐了好几个小时的故障排除。它必须与 Java 中的 String 可以是 null (因此对应于 Kotlin 中的可为空的 String?)有关,而 Java 中的 long 是原始的并且永远不可能是 null 所以它映射与 Kotlin 中的 Long 很好......所以这一切都是为了帮助编译器映射签名!
      猜你喜欢
      • 2020-01-27
      • 2018-08-25
      • 2022-01-01
      • 2020-02-09
      • 2018-05-29
      • 2018-11-25
      • 1970-01-01
      • 2016-12-10
      • 2013-05-05
      相关资源
      最近更新 更多