【Scala】新しいDBライブラリを使ってみた

千葉大学 Advent Calendar 2019の18日目の記事

これが4つ目だけど、正直きつかったw
こんな薄い内容で、思いついたことをひたすら殴り書きするだけでもかなり疲れた😇
でも短期間にこんなに書いたのは自分史上初だし、いい経験になった。
インプットだけだと成長しないから今後も定期的にアウトプットしていきたい!

はじめに

getquillとdoobieと言うScalaのDB操作ライブラリについて書く。
Slickからの移行で調べたことをまとめる感じでいこうかなと。

まずそれぞれの特徴を簡単に

  • doobie

    1. 生のSQLを使用する
    2. DBから得たメタデータとクエリから不整合を検出する機能が充実している
  • getquill

    1. クエリはSlickと同じような感覚で記述することができる
    2. Slickのようなテーブルとのマッピング定義する必要がない

???「doobieで生SQLを生成してdoobieで実行すれば、良い所取りできるのでは?」

設定周り

おまじない

val dc: DoobieContext.MySQL[SnakeCase] = new DoobieContext.MySQL(SnakeCase)
import dc._

SnakeCaseってなんぞや。。。
軽く見た感じだと、SQL周りの設定クラスのようだ?(自信なし)
例:Returning Intoを使えないようにする

DBセッション

val ec: ExecutionContext = ???
val ctx: Resource[Task, HikariTransactor[Task]] = 
HikariTransactor.newHikariTransactor[Task](
    "com.mysql.jdbc.Driver",
    "jdbc:mysql://localhost:3306/mydatabase",
    "username",
    "password",
    ec,
    Blocker.liftExecutionContext(ec)
  )

connection poolはHikariTransactorを使った

データを取得してみる

import doobie.implicits._
case class Account(id: String, name: String)
val q = quote { query[Account].filter(_.id == lift("123")) }
val res: Task[Option[Account]] = ctx.use(x => run(q).transact(x).map(_.headOption))

このコードはsql文だとselect * from account where id = 123になるはず。
特に設定しないとクラス名がテーブル名になるみたい。

doobie.implicits._をimportしないといけないので注意

なおlift("123")を"123"にするとエラーになる

[error] Found the following free variables: id.
[error] Quotations can't reference values outside their scope directly. 
[error] In order to bind runtime values to a quotation, please use the method `lift`.
[error] Example: `def byName(n: String) = quote(query[Person].filter(_.name == lift(n)))`

テーブル名やカラム名をカスタマイズしたい

query[Account]ってやると、SQL文でselect * from accountとなるが、
クラス名と、テーブル名が一致しない場合が多いだろう。
同じくクラスの変数名と、カラム名も一致しない事がある。

その時はschemaMetaを使う事で、テーブル名とカラム名を任意のものにする事ができる!

val dc: DoobieContext.MySQL[SnakeCase] = new DoobieContext.MySQL(SnakeCase)
import dc._
case class Account(accountId: String)
implicit lazy val schemaMeta =
    schemaMeta[Account]("account_db", _.accountId -> "id")

こうする事でselect * from account_dbとなる。

Slickと比べて

Slickは

  1. テーブル用CaseClassを作るときにDB ProfileのImportが必要だったりとライブラリ依存な部分が大きくて面倒

  2. そしてこれが一番大きい気がするが、Queryをあらかじめコンパイルしておかないと、実行毎にコンパイルが走って結構時間がかかる。小規模であればそんなに影響はないけど、、、アドテクコンペの時はこのせいで大変なことに^^

最後に

  • 個人的にはもうSlickを使うことはなさそう。(移行も面倒だしw)
  • getquill-doobieはSlickとクエリの書き方も近くて移行もスムーズだった。getquillとdoobieの両方が合わさって最強!

Slickでできてた#filter#inSetはどうやるんだろう。。。?

コメント

タイトルとURLをコピーしました