【问题标题】:Multiple queries in a single transaction with Doobie?使用 Doobie 在单个事务中进行多个查询?
【发布时间】:2021-02-28 00:17:00
【问题描述】:

假设我有两个案例类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 作为数据库后端,并且事务有很多与之相关的开销。我希望在一个事务中执行这两个查询并让它返回一个 List[T] 对象。有没有办法做到这一点?

【问题讨论】:

    标签: scala scala-cats doobie


    【解决方案1】:

    如果您不关心这两个查询的顺序,我建议您将 compile 每个查询独立地转换为 ConnectionIO[List[A]],使用 mapN 组合它们(因为 ConnectionIO[T] 具有 Apply 实例)和 @987654326 @合并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)
        }
    }
    

    【讨论】:

      【解决方案2】:

      我也得到了一个解决方案,只需将流相互附加

      transactor.use { xa =>
          val stream = generateQuery1.stream ++ generateQuery2.stream
          stream.compile.toList.transact(xa)
      }.unsafeRunSync
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-10-13
        • 2020-01-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-22
        • 2016-12-04
        相关资源
        最近更新 更多