gpt4 book ai didi

kotlin - 为什么执行挂起的存储库函数而不执行非挂起的存储库函数?

转载 作者:行者123 更新时间:2023-12-05 03:35:38 25 4
gpt4 key购买 nike

我有这个服务方式:

@Transactional
override suspend fun deleteByCarId(carId: Long) {
routeRepository.deleteByCarId(carId)
routePlanRepository.deleteByCarId(carId)
carRepository.deleteById(carId)
}

路线计划(中间)和汽车(最后一行)被删除,但删除了 routeRepository不被执行。

interface RouteRepository : CoroutineCrudRepository<Route, Long> {
fun deleteByCarId(carId: Long)
// ...
}
interface RoutePlanRepository : CoroutineCrudRepository<RoutePlan, Long> {
suspend fun deleteByCarId(carId: Long)
// ...
}

所以,我发现这可能是因为 RouteRepository错过了 suspend关于删除方法,但有人可以解释一下,为什么这很重要?


编辑 1

通过进一步考虑更一般的情况,我认为创建 Flow 的非暂停存储库函数似乎不一定被标记为suspend .但我不明白为什么。所有其他方法似乎都需要 suspend - 但为什么?通常我可以从协程运行一个非挂起函数并执行它(当然我们不应该因为它可能会阻塞线程 - 对吧?)。

我的假设是创建一个 Flow不需要是可挂起的,因为创建它的 Action 很快,只有它的订阅最终会执行查询。

在上面的例子中没有订阅 Flow因为该方法返回 Unit - 这就是不执行删除的原因?

但是,我还是不明白,为什么要用suspend标记存储库方法?改变行为。现在查询的创建本身就是一个异步操作,因此它(删除查询的创建)成为整个请求处理链的一部分?

但我希望在挂起函数中创建查询不会自动订阅?谁能解释一下?

编辑 2

我创建这个问题是因为我认为应该更好地记录什么是可能的,什么不是:https://github.com/spring-projects/spring-data-commons/issues/2503

文档目前指出 delete需要 suspend但没有明确提及:

For return values, the translation from Reactive to Coroutines APIs is the following:

fun handler(): Mono<Void> becomes suspend fun handler()

fun handler(): Mono<T> becomes suspend fun handler(): T or suspend fun handler(): T? depending on if the Mono can be empty or not (with the advantage of being more statically typed)

fun handler(): Flux<T> becomes fun handler(): Flow<T>

https://docs.spring.io/spring-data/r2dbc/docs/current/reference/html/#kotlin.coroutines.reactive

最佳答案

我觉得很奇怪,当你在扩展 CoroutineCrudRepository 的接口(interface)中定义非挂起函数时,没有警告甚至编译错误。

您可能知道,挂起函数是协程的核心概念。 suspend 关键字意味着这个函数可以是阻塞的,它可以暂停并在稍后恢复。当您需要执行长时间运行的操作但又不希望您的线程在等待它完成时被阻塞时,这非常有用。数据库调用只是这些长时间运行操作的一个示例,这就是为什么所有 CoroutineCrudRepository 方法都被定义为挂起函数的原因。您可以在源代码中查看 https://github.com/konrad-kaminski/spring-kotlin-coroutine/blob/master/spring-data-mongodb-kotlin-coroutine/src/main/kotlin/org/springframework/data/repository/coroutine/CoroutineCrudRepository.kt .

当你执行以下操作时,我仍然觉得没有警告甚至编译错误很奇怪,但也许编译器无法确定只应将挂起函数添加到这样的接口(interface):

interface RouteRepository : CoroutineCrudRepository<Route, Long> {
fun deleteByCarId(carId: Long)
// ...
}

关于kotlin - 为什么执行挂起的存储库函数而不执行非挂起的存储库函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69842380/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com