Создайте динамический запрос UPDATE в Slick 3

Я ищу способ сгенерировать запрос UPDATE для нескольких столбцов, которые известны только во время выполнения.

Например, учитывая List[(String, Int)], как мне сгенерировать запрос в форме UPDATE <table> SET k1=v1, k2=v2, kn=vn для всех пар ключ/значение в списке?

Я обнаружил, что при наличии одной пары ключ/значение простой SQL-запрос может быть построен как sqlu"UPDATE <table> SET #$key=$value (где ключ получен из надежного источника, чтобы избежать инъекции), но мне не удалось обобщить это на список обновлений. без выполнения запроса для каждого.

Это возможно?


person Luke Cycon    schedule 24.09.2015    source источник


Ответы (1)


Это один из способов сделать это. Здесь я создаю определение таблицы T с именами таблиц и столбцов (TableDesc) в качестве неявных аргументов. Я бы подумал, что должна быть возможность установить их явно, но я не мог этого найти. Например, создание экземпляров запроса таблицы, aTable и bTable. Затем я вставляю и выбираю некоторые значения и, в конце концов, обновляю значение в bTable.

import slick.driver.H2Driver.api._
import scala.concurrent.Await
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration
import scala.util.{Failure, Success}

val db = Database.forURL("jdbc:h2:mem:test1;DB_CLOSE_DELAY=-1", "sa", "", null, "org.h2.Driver")

case class TableDesc(tableName: String, intColumnName: String, stringColumnName: String)

class T(tag: Tag)(implicit tableDesc: TableDesc) extends Table[(String, Int)](tag, tableDesc.tableName) {
    def stringColumn = column[String](tableDesc.intColumnName)

    def intColumn = column[Int](tableDesc.stringColumnName)

    def * = (stringColumn, intColumn)
}

val aTable = {
    implicit val tableDesc = TableDesc("TABLE_A", "sa", "ia")
    TableQuery[T]
}

val bTable = {
    implicit val tableDesc = TableDesc("TABLE_B", "sb", "ib")
    TableQuery[T]
}

val future = for {
    _ <- db.run(aTable.schema.create)
    _ <- db.run(aTable += ("Hi", 1))
    resultA <- db.run(aTable.result)
    _ <- db.run(bTable.schema.create)
    _ <- db.run(bTable ++= Seq(("Test1", 1), ("Test2", 2)))
    _ <- db.run(bTable.filter(_.stringColumn === "Test1").map(_.intColumn).update(3))
    resultB <- db.run(bTable.result)
} yield (resultA, resultB)
Await.result(future, Duration.Inf)
future.onComplete {
    case Success(a) => println(s"OK $a")
    case Failure(f) => println(s"DOH $f")
}
Thread.sleep(500)

В конце у меня есть оператор сна, чтобы утверждать, что Future.onComplete получает время для завершения до завершения приложения. Есть ли другой способ?

person thoredge    schedule 25.09.2015