LoginSignup
21
19

More than 5 years have passed since last update.

Slick3 のクエリ合成メモ

Posted at

Slick3ではクエリ(DBIOAction)の構築と実行とが分離されていて、予めクエリを合成した上で一つの機能にしてから実行できる。

そのうちいくつか試したものを備忘録としてメモする。

存在しなければINSERTを実行 その1

アカウントテーブルのTableQueryに対して、アプリケーション初期化時にレコードがなければINSERTを実行する方法

// class Accounts(tag: Tag) extends Table[Account]("ACCOUNTS", tag) { ... }
val accounts = TableQuery[Accounts]

val initialAccount = Account(...)

val insertIfEmpty = accounts.length.result.filter(_ == 0).flatMap(_ => accounts += initialAccount) // クエリ構築

db.run(insertIfEmpty) // 実行
  • accounts.length.result が一つ目のクエリ。.resultによってRep[Int]からDBIOAction[Int, NoStream, Read]への変換が行われる。
  • DBIOAction[R,S,E]R のコレクションとみなしたいくつかの操作が可能で、今回の例では filter, flatMap を用いている。
  • .filter(_ == 0) により、レコードがない場合だけ処理を続行するようにする
  • .flatMap { _ => accounts += initialAccount } でこれまでの結果(0)はとりあえず無視して、initialAccountの挿入を実行する。挿入処理がDBIOActionであるため、flatMapで合成できる。

存在しなければINSERTを実行 その2

特定のIDが存在しなければ挿入を実行し true を返す。IDがすでに存在している場合はINSERTは実行せずに false を返す。

val account = Account(...)

val insertIfNotExists = accounts.filter(_.id === account.id).exists.result.flatMap {
  case true => DBIO.successful(false)
  case false => (accounts += account).andThen(DBIO.successful(true))
}.transactionally
  • .filter(_.id === account.id).exists.result で指定のIDが存在するかどうか試す
  • true(存在する)の場合は false を返すアクションを生成して返す
  • false(存在しない)の場合は挿入を実行してからtrueを返すアクションを生成して返す
  • .transactionally で一連のトランザクション処理にする
21
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
19