1

我正在阅读 Doobie 文档并尝试在事务中进行简单的获取或创建。我从第一个查询中获得了一个选项,并尝试getOrElse在 else 中执行并运行插入,但是我一直value map is not a member of AnygetOrElse调用中得到 a。获取现有行或创建新行instances并在事务中返回该结果的正确方法是什么?

import doobie._
import doobie.implicits._
import cats._
import cats.effect._
import cats.implicits._
import org.joda.time.DateTime

import scala.concurrent.ExecutionContext

case class Instance(id : Int, hostname : String)

case class User(id : Int, instanceId: Int, username : String, email : String, created : DateTime)

class Database(dbUrl : String, dbUser: String, dbPass: String) {

  implicit val cs = IO.contextShift(ExecutionContext.global)

  val xa = Transactor.fromDriverManager[IO](
    "org.postgresql.Driver", dbUrl, dbUser, dbPass
  )

  def getOrCreateInstance(hostname: String) = for {
    existingInstance <- sql"SELECT id, hostname FROM instances i WHERE i.hostname = $hostname".query[Instance].option
    ensuredInstance <- existingInstance.getOrElse(sql"INSERT INTO instances(hostname) VALUES(?)".update.withGeneratedKeys[Instance]("id", "hostname"))
  } yield ensuredInstance

}
4

2 回答 2

5

感谢#scala/freenode 聊天室的人们,我得到了以下答案。我在这里发布它是为了完整性,如果人们有兴趣在没有其他答案的理解的情况下这样做。

  def getOrCreateInstance(hostname: String): ConnectionIO[Instance] =
        OptionT(sql"SELECT id, hostname FROM instances i WHERE i.hostname = $hostname".query[Instance].option)
          .getOrElseF(sql"INSERT INTO instances(hostname) VALUES($hostname)".update.withGeneratedKeys[Instance]("id", "hostname").compile.lastOrError)
于 2018-12-24T05:29:19.050 回答
0

我相信这样的事情应该对你有用,

def getOrCreateInstance(hostname: String): ConnectionIO[Instance] = for {
  existingInstance <- sql"SELECT id, hostname FROM instances i WHERE i.hostname = $hostname".query[Instance].option
  ensuredInstance <- existingInstance.fold(sql"INSERT INTO instances(hostname) VALUES($hostname)".update.withGeneratedKeys[Instance]("id", "hostname").take(1).compile.lastOrError)(_.pure[ConnectionIO])
} yield ensuredInstance

您正在编译 fs2Stream并在现有实例ConnectionIO已经存在的情况下将其提升到 a 中。

于 2018-12-23T00:00:17.760 回答