以前からちょっとしたものを作るときに便利なIO関連のユーティリティをまとめたScalaライブラリを作っていたのですが、最近ScalaのIOライブラリはbetter-filesがよさげなのでこちらに乗り換えるのがいいかなと思ったところ、自作ライブラリにあるJDBC周りの機能がbetter-filesにはなかったので自作ライブラリから単独で使えるライブラリとして切り出してみました。
こんな感じの依存関係をbuild.sbt
に追加して、
resolvers += "amateras-repo" at "http://amateras.sourceforge.jp/mvn/" libraryDependencies += "com.github.takezoe" %% "better-jdbc" % "1.0.0"
以下のインポート文で使えるようになります。
import better.jdbc._
SELECTはこんな感じ。SQLは文字列またはsql
というString Interpolationでパラメータを埋め込んだものを渡すことができます。コールバックにResultSet
が渡されるのでそこで必要な値を抽出します。DBUtilsみたいな感じですね。
val users: Seq[(Int, String)] = DB.autoClose(conn) { db => db.select("SELECT * FROM USERS"){ rs => (rs.getInt("USER_ID"), rs.getString("USER_NAME")) } }
selectFirst
で先頭の1件だけをOption
で取得できます。カウントとかを取得する場合用にselectInt
とかselectString
という便利メソッドもあります。
val user: Option[(Int, String)] = DB.autoClose(conn) { db => db.selectFirst(sql"SELECT * FROM USERS WHERE USER_ID = $userId"){ rs => (rs.getInt("USER_ID"), rs.getString("USER_NAME")) } }
ファクトリメソッドを渡してケースクラスにマッピングすることもできます。
case class User(userId: Int, userName: String) val users: Seq[User] = DB.autoClose(conn) { db => db.select("SELECT USER_ID, USER_NAME FROM USERS", User.apply) }
更新系はupdate
メソッドを使います。
DB.autoClose(conn) { db =>
db.update(sql"INSERT INTO USERS (USER_ID, USER_NAME) VALUES ($userId, $userName)")
}
トランザクションはこんな感じ。
DB.autoClose(conn) { db => db.transaction { db.update(sql"DELETE FROM GROUP WHERE USER_ID = $userId") db.update(sql"DELETE FROM USERS WHERE USER_ID = $userId") } }
簡単なものですが、こういうの何度も自作している気がするのですぐに使える状態のライブラリがあると便利かなと思います。