Project Reactor 中的方法签名和错误处理

问题描述 投票:0回答:1

有点绕圈子试图处理一个场景,我可能只是不以“反应性”方式看待它,只是需要休息一下才能看到更大的图景。

假设我想将用户保存到数据库中,但首先我需要查看是否存在具有该名称的人,所以:

使用

ReactiveCrudRepository

的存储库
interface UserRepository : ReactiveCrudRepository<User, Long> {

    @Query("SELECT * FROM user WHERE name = :name LIMIT 1")
    fun findByName(name: String): Mono<User>

    fun saveUser(user: User): Mono<User>

}

企业代码

fun saveUser(user: User): Mono<User> {
  return repository.findByName(user.name)
    .flatMap { existingUser ->
      return Mono.error(UserExistsException())  //A Mono<User> is expected 
    }
    .switchIfEmpty {
      return repository.saveUser(user)
    }
}

存储库在空值上返回 Mono.empty() (即,如果没有找到具有该名称的用户)这一事实似乎限制了我处理用户已存在的情况的方式,因为我想抛出错误所以调用者以他的方式处理这个问题。

我尝试在存储库端返回

Mono<Optional<User>>
,所以我从未得到
empty
,但库不允许这样做。

我对响应式总体来说是新手,我想让事情变得简单,但又在良好实践的范围内,那么我应该如何处理这个问题呢?

flatMap
是我想要的吗?我需要在成功时返回一个 User,理想情况下在失败时返回一个异常,但我不能简单地将其放入
flatMap
中,因为它要求
Mono<User>

spring-boot kotlin project-reactor
1个回答
0
投票

在 Kotlin 中,与 Java 不同,

return
不在 lambda 内部使用。这只允许在
inline
lambda 内实现提前返回

此外,您的代码还有两个问题:

  1. switchIfEmpty
    接受
    Mono
    值,但不接受 lambda。
  2. Mono.error
    需要通用参数
    T

所以这是固定代码:

fun saveUser(user: User): Mono<User> =
    repository.findByName(user.name)
        .flatMap { existingUser ->
            Mono.error<User>(UserExistsException())
        }.switchIfEmpty(repository.saveUser(user))

如果您使用 Kotlin 但使用 Spring,建议使用协程并尽可能避免使用 Project Reactor。为此,我们可以使用

UserRepository
而不是
CoroutineCrudRepository
重新定义
ReactiveCrudRepository

import org.springframework.data.repository.kotlin.CoroutineCrudRepository

interface UserRepository : CoroutineCrudRepository<User, Long> {
    @Query("SELECT * FROM user WHERE name = :name LIMIT 1")
    suspend fun findByName(name: String): User?

    fun saveUser(user: User): User
}

生成的代码看起来也更好了。

suspend fun saveUser(user: User): User {
    val foundUser = repository.findByName(user.name)
    return if (foundUser == null) repository.saveUser(user)
    else throw UserExistsException()
}
© www.soinside.com 2019 - 2024. All rights reserved.