What is doobie? - database access for scala -

Preview:

Citation preview

What is doobie ?- database access for scala -

2016-10-1第十七回 #渋谷java

Me島本 多可子(@chibochibo03)

株式会社ビズリーチ CTO室

普段はScalaを書いてます

直近の著書です →

Today's topic

doobieでできることをざっくり紹介

functional programming的な話はしません

scalazの細かい話はしません

Background

● Slick○ ScalaでメジャーなDBアクセスライブラリ

● 色々な意見があるが・・・

弁解できないのが

Performance

Hard!!

● whole query preparation timehttp://stackoverflow.com/questions/39725886/typical-performance-in-slick-ver-3-1-1

● join explain

(´・ω・`)ショボーン

他を模索してみる・・・

doobie

https://github.com/tpolecat/doobie

● ScalaのDBアクセスライブラリ

● ORMではない(重要)

● JDBCを使ったプログラムを書く手段を提供

doobie

キーワードは

pure FP SQLI/O

Supported releases

● 0.3.x (最新は0.3.0)○ JDK 1.8+○ Scala 2.10, 2.11, 2.12

● 0.2.x (最新は0.2.4)○ JDK 1.7+○ Scala 2.10, 2.11

doobie is pre-1.0

● 開発が活発

● 大きな変更もありえる

○ マイナーリリース(0.x)で非推奨になることも

Setup

● build.sbt

libraryDependencies ++= Seq( "org.tpolecat" %% "doobie-core" % 0.3.0)

Setup

● 必要なimport

import doobie.imports._import scalaz._, Scalaz._, concurrent.Task

Setup

● 接続情報

val xa = DriverManagerTransactor[Task]( "org.h2.Driver", "url", "user", "password")

Select

val id = 1val res = sql"select * from user where uid = $id" .query[User] .unique .transact(xa)

Select

val id = 1val res = sql"select * from user where uid = $id" .query[User] .unique .transact(xa)

(注)まだ実行されてないよ!

// Query0[User]

// ConnectionIO[User]

// Task[User]

Benefit

● actually constructing PreparedStatement○ SQLはPreparedStatementで実行

○ パラメータはsetString, setIntなどで設定される

● 破壊的なSQLにならない

● ソースコードだけで完結する

○ 別ファイルを行き来しなくてよい

Benefit

● 非同期が前提のものとの相性がよい

○ たとえばhttp4s

val service = HttpService { case req @ GET -> Root / "users"/ IntVar(uid) => Ok(findUser(uid))}

def findUser(uid: Int): Task[User] = ...

EntityEncoderを定義すればcase classをそのまま返せる

Insert

sql"insert into user (name, age) values (${u.name}, ${u.age})".update.run // ConnectionIO[Int]

Insert

for { id <- sql"insert into ...".update .withUniqueGeneratedKeys[Int]("uid") _ <- sql"insert into ... values ($id, ...)".update .run} yield id

特徴的な機能

What is YOLO mode ?

● REPLで便利な機能

○ transact(xa)してforeach(println)するのは煩雑

● 面倒な呼び出しをショートカットできる

○ quick・・結果を標準出力に

○ check・・Typecheckingを行う(後述)

YOLO - quick

import xa.yolo._

sql"select * from user where uid = $id" .query[User] .quick .unsafePerformSync

必要

// Task[Unit]

Typechecking (experimental)

● DBスキーマに対してクエリを検証

○ マッピングする型が正しいか

● run-time check

YOLO - check

import xa.yolo._

sql"select * from user where uid = $id" .query[User] .check .unsafePerformSync

必要

YOLO - check

✓ SQL Compiles and Typechecks✕ C01 UID INTEGER (INTEGER) NOT NULL → String - INTEGER (INTEGER) is ostensibly coercible to String according to the JDBC specification but is not a recommended target type. Fix this by changing the schema type to CHAR or VARCHAR; or the Scala type to Int or JdbcType.✓ C02 NAME VARCHAR (VARCHAR) NOT NULL → String...

Unit Testing (experimental)

● UTでクエリの検証をサポート

○ 現在はSpecs2のみ

● doobie-contrib-specs2を依存関係に追加

○ doobie.contrib.specs2.analysisspec.AnalysisSpecをミッ

クスイン

Unit Testing (experimental)

object xxx extends Specification with AnalysisSpec { val transactor = DriverManagerTransactor[Task]( "org.mysql.jdbc.Driver", "url", "user", "password" ) check(sql"select * from user".query[User])}

(注)存在するスキーマに対して実行

yoloのインポートは不要

まとめ

Conclusion

● スタイル

○ SQLを書く

○ functional programming● SQLの妥当性はテストで行う

● scalazを扱うものと相性がよい

○ http4sとか

Conclusion

● 前述したことがデメリットとなるケースも

● 機能が大きく変わる可能性あり

○ 1.0まで遠い・・・

● 吟味してから使いましょう

Recommended