如何在Quarkus/Vert.x响应式SQL客户端事务中使用Kotlin协程
解决方案
你需要通过Mutiny提供的协程适配工具,把挂起函数逻辑包装成符合withTransaction入参要求的Uni类型,调整后的可运行代码如下:
val client : PgPool ... suspend fun someServiceFunction () { client.withTransaction { connection -> // 将协程代码块包装为Uni,匹配入参要求 Uni.createFrom().coroutine { // 此处可正常调用所有挂起函数 repository.save(connection, entity).awaitSuspending() // 其他业务逻辑,最后一行为Uni的返回值 } }.awaitSuspending() // 外层Uni转为挂起调用,接入当前协程上下文 }
前置依赖
确保项目引入了Mutiny的Kotlin协程适配依赖,Quarkus项目推荐直接引入官方协程扩展:
// Gradle 依赖示例 implementation("io.quarkus:quarkus-kotlin-coroutines") // 若未使用Quarkus,直接引入Mutiny Kotlin适配包 implementation("io.smallrye.reactive:mutiny-kotlin:latest.release")
原理解释
Uni.createFrom().coroutine { }可以将内部的协程代码块包装为Uni对象,内部支持调用任意suspend函数,完全符合withTransaction的入参签名要求- 外层
withTransaction本身返回Uni<T>,调用awaitSuspending()即可将整个事务逻辑接入当前协程,不会阻塞线程 - 协程块内抛出异常时,会自动传递给Uni触发失败信号,
withTransaction会自动执行事务回滚,和原生方法的事务语义完全一致
可选优化:封装扩展函数
你可以封装一个通用的协程适配扩展,后续调用更简洁:
suspend fun <T> Pool.withTransactionSuspend(block: suspend (SqlConnection) -> T): T { return withTransaction { conn -> Uni.createFrom().coroutine { block(conn) } }.awaitSuspending() } // 调用侧代码简化为 suspend fun someServiceFunction () { client.withTransactionSuspend { connection -> repository.save(connection, entity).awaitSuspending() // 其他业务逻辑 } }
内容的提问来源于stack exchange,提问作者Ahmet K
相关产品推荐
相关产品推荐

