与 Doobie 的单笔交易中的多个查询?
Multiple queries in a single transaction with Doobie?
假设我有两个案例 类 C1
和 C2
,每个案例都继承自特征 T
。我有两个 Query0
对象,这些对象由 类 Query0[C1]
和 Query0[C2]
参数化。目标是当我执行这些查询时,我想获得一个 List[T]
包含这两个查询的结果。现在我可以很好地处理单独的事务。
def executeQuery[A <: T](query: Query0[A]): List[A]=
transactor.use { xa => query.stream.compile.toList.transact(xa) }.unsafeRunSync
val query1: Query0[C1] = generateQuery1
val query2: Query0[C2] = generateQuery2
val results: List[T] = executeQuery(query1) ++ executeQuery(query2)
问题是我使用 BigQuery 作为数据库后端,事务有很多与之相关的开销。我希望在一个事务中执行这两个查询并让它 return 一个 List[T] 对象。有办法吗?
如果您不关心这两个查询的顺序,我建议您 compile
每个查询独立进入 ConnectionIO[List[A]]
,使用 mapN
组合它们(因为 ConnectionIO[T]
有 Apply
个实例)和 transact
在一次交易中组合 ConnectionIO[List[A]
:
import cats.effect.{Async, ContextShift, Resource}
import cats.syntax.apply._
import doobie.Query0
import doobie.implicits._
import doobie.util.transactor.Transactor
class SomeDAO[F[_]: Async: ContextShift, T] {
val transactor: Resource[F, Transactor[F]] = ???
def compile[A <: T](query: Query0[A]): doobie.ConnectionIO[List[A]] =
query.stream.compile.toList
def executeTwo[A <: T](query1: Query0[A], query2: Query0[A]): F[List[A]] =
transactor.use { xa =>
(compile(query1), compile(query2))
.mapN(_ ++ _)
.transact(xa)
}
}
我也得到了一个解决方案,只需将流附加到彼此即可
transactor.use { xa =>
val stream = generateQuery1.stream ++ generateQuery2.stream
stream.compile.toList.transact(xa)
}.unsafeRunSync
假设我有两个案例 类 C1
和 C2
,每个案例都继承自特征 T
。我有两个 Query0
对象,这些对象由 类 Query0[C1]
和 Query0[C2]
参数化。目标是当我执行这些查询时,我想获得一个 List[T]
包含这两个查询的结果。现在我可以很好地处理单独的事务。
def executeQuery[A <: T](query: Query0[A]): List[A]=
transactor.use { xa => query.stream.compile.toList.transact(xa) }.unsafeRunSync
val query1: Query0[C1] = generateQuery1
val query2: Query0[C2] = generateQuery2
val results: List[T] = executeQuery(query1) ++ executeQuery(query2)
问题是我使用 BigQuery 作为数据库后端,事务有很多与之相关的开销。我希望在一个事务中执行这两个查询并让它 return 一个 List[T] 对象。有办法吗?
如果您不关心这两个查询的顺序,我建议您 compile
每个查询独立进入 ConnectionIO[List[A]]
,使用 mapN
组合它们(因为 ConnectionIO[T]
有 Apply
个实例)和 transact
在一次交易中组合 ConnectionIO[List[A]
:
import cats.effect.{Async, ContextShift, Resource}
import cats.syntax.apply._
import doobie.Query0
import doobie.implicits._
import doobie.util.transactor.Transactor
class SomeDAO[F[_]: Async: ContextShift, T] {
val transactor: Resource[F, Transactor[F]] = ???
def compile[A <: T](query: Query0[A]): doobie.ConnectionIO[List[A]] =
query.stream.compile.toList
def executeTwo[A <: T](query1: Query0[A], query2: Query0[A]): F[List[A]] =
transactor.use { xa =>
(compile(query1), compile(query2))
.mapN(_ ++ _)
.transact(xa)
}
}
我也得到了一个解决方案,只需将流附加到彼此即可
transactor.use { xa =>
val stream = generateQuery1.stream ++ generateQuery2.stream
stream.compile.toList.transact(xa)
}.unsafeRunSync