Doobie.Создайте .update.withGeneratedKeys () и .update.run - PullRequest
3 голосов
/ 30 мая 2019

Ссылка на этот вопрос.
Я хочу вставить некоторую сущность по какому-либо условию.Он может быть вставлен или нет.Если условие истинно, сущность вставляется.Я хочу вставить некоторые другие данные в различные таблицы.Это выглядит так:

val q = sql"insert into some_table (some_field) select 42 where ...(some condition)"

val inserts = List(
  sql"insert ...",
  sql"insert ...",
  sql"insert ..."
)

for {
  id <- q.update.withGeneratedKeys[Long]("id")   
  _ <- inserts.reduce(_ ++ _).update.run
} yield id

Проблема в том, что это не компилируется, потому что первая вставка - fs2.Stream, а вторая - нет.

Я пытался заменить _ <- inserts.reduce... с _ = inserts.reduce.Приложение может скомпилироваться, но inserts во второй строке не происходит.


UPD
Мой возможный способ решения этой проблемы:

...
for {
  idOpt <- q.update.withGeneratedKeys[Long]("id").compile.last   
  _ <- idOpt.fold(0.pure[ConnectionIO])(_ => inserts.reduce(_ ++ _).update.run)
} yield idOpt

это работает, но имхо это не красивоЕсть ли лучший способ сделать это?

1 Ответ

1 голос
/ 15 июня 2019

Один из способов выполнения пакетных вставок - если у вас есть похожие данные - это использовать updateMany - , см. Документ :

import doobie._
type PersonInfo = (String, Option[Short])

def insertMany(ps: List[PersonInfo]): ConnectionIO[Int] = {
  val sql = "insert into person (name, age) values (?, ?)"
  Update[PersonInfo](sql).updateMany(ps)
}

// Some rows to insert
val data = List[PersonInfo](
  ("Frank", Some(12)),
  ("Daddy", None))

Кроме того, если вы удалите .compile.last, вы можете использовать тот факт, что если ваш результат Stream q.update.withGeneratedKeys[Long]("id") равен empty, вы 'рано выйдете' из for-comprehension.

В общем, вот что вы могли бы сделать:

import fs2.Stream

val result =
  // Now the for-comprehension operates on a Stream instead of an Option
  for {
    r <- q.update.withGeneratedKeys[Long]("id")   
    _ <- Stream.eval(insertMany(data)) // insertMany(data) is defined like in the snippet above
  } yield r

result.compile.last
...