Screaming Loud

研究・プログラミングなど気づいたことをメモをしています。読書記録はこちらに記載しています。https://bookmeter.com/users/75944

scalaのクエリビルダー「quill」を使ってみた

takezoeさんがquillを紹介していたので、
Scalaの新しいデータベースアクセスライブラリ「quill」を試してみた - たけぞう瀕死ブログ
実際にどんな感じで使えるのかを試してみました。

http://getquill.io/getquill.io

結論、Slick2系から置き換えるのはなかなかありかなと思っています。

直接的なクエリサンプルは、上記のtakezoeさんのブログやドキュメントに書いてあるので、もうちょっと踏み込んだ内容を紹介したいと思います。

Database Access

今回は自分がよく使うMySQLにアクセスするように試しました。

動かすのに必要な最低限のlibraryは以下です。

libraryDependencies ++= {
  Seq(
    "mysql"       %  "mysql-connector-java" % "5.1.36",
    "io.getquill" %% "quill-jdbc" % "0.4.2-SNAPSHOT",
    "com.zaxxer" % "HikariCP" % "2.4.3",
    "com.typesafe" % "config" % "1.3.0"
  )
}

HikariCPとTypesafeConfigがないと、動きません。
また、このバージョンの場合、Java8でないと動きません。

build.sbtを上記のように作って上げれば、ドキュメントに書いてあるようなクエリをコンパイルすることができます。
quill_example/UserDao.scala at master · moc-yuto/quill_example · GitHub

テーブル名

Slickと違ってテーブル名を文字列で指定する部分はなく、queryのcase classがそのままテーブル名に使われます。

以下の例だと、case classのUsersがそのままテーブル名として使われます。

case class Users(id: Int, name: String, age: Int)

val find = quote { (id: Int) =>
  query[Users].filter(u => u.id == id)
}

トランザクション

やはり、実践投入するならトランザクション処理は必須となりますが、本家ドキュメントには書かれていません。
しかし、テストコードにはしっかり書かれています。

書き方としてはとても単純で、以下のようにtransaction関数でくくってあげればいいだけです。

db.transaction{
  val a = db.run(UserDao.findName)(name).headOption
  if (a.isEmpty) db.run(UserDao.insert)(name, age)
  else db.run(UserDao.update)(a.get.id, age)
  throw new Exception
}

このように書くと以下の様なクエリが流れました。

2016-03-06T15:29:28.783495Z   13 Query  SET autocommit=1
2016-03-06T15:29:28.783727Z   13 Query  set session transaction read write
2016-03-06T15:29:28.783987Z   13 Query  SELECT @@session.tx_isolation
2016-03-06T15:29:28.828915Z    4 Query  SELECT x1.id, x1.name, x1.age FROM users x1 WHERE x1.name = 'aaa'
2016-03-06T15:29:28.875733Z    4 Query  select @@session.tx_read_only
2016-03-06T15:29:28.877008Z    4 Query  select @@session.tx_read_only
2016-03-06T15:29:28.877849Z    4 Query  UPDATE users SET age = 1323 WHERE id = 2
2016-03-06T15:29:28.890415Z    4 Query  rollback
2016-03-06T15:29:28.891274Z    4 Query  SET autocommit=1

実際のトランザクションのコードは以下です。
quill_example/Users.scala at master · moc-yuto/quill_example · GitHub

感想

Slickよりも冗長な部分が減ったな―と感じます。
それでいてSlick風な書き方なので、書きやすいと思います。
また、Slickでは生成できないSQLを作れるDSLが多数あるので、細かいハンドリングがしやすいと感じました。


以下は動かしたサンプルです。
github.com