この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
Slick 2.0リリース
2014年1月に、Slickの2.0がリリースされました。 2.0ではRDB以外のサポートも強化され、DBスキーマのリバースエンジニアリング機能も可能になっています。
Slickとは
Slickとは、元々ScalaQueryと呼ばれていたもので、TypeSafe社の開発しているORMです。 Scalaのコレクションを使用するかのごとく、データストアの操作が可能です。 また、Playframework2.3(2014/Q1予定)からはAnormに代わりSlickが標準のDBライブラリとなる予定です。 参考:以前のSlick記事
環境構築
今回使用した動作環境は以下のとおりです。sbtはインストールしておきましょう。
- OS : MacOS X 10.9.1
- sbt : 0.13.1
プロジェクトのテンプレート作成のためgiter8を使用するので、Homebrewでインストールしておいてください。
% brew install giter8
今回Slick2.0で使用するためのRDBとして、MySQLを使用します。 そして適当なデータベースをcreate database文で作成しておいてください。
プロジェクトのセットアップ
giter8を使ってsbtプロジェクトのひな形を作成します。
% g8 pmandera/basic-scala-project
次に、build.sbtに依存ライブラリを追記します。MySQLのJDBCドライバ、slick、slf4jを追加しましょう。
・
・
libraryDependencies ++= Seq(
"org.specs2" %% "specs2" % "2.3.7" % "test",
"mysql" % "mysql-connector-java" % "5.1.28",
"com.typesafe.slick" %% "slick" % "2.0.0",
"org.slf4j" % "slf4j-nop" % "1.6.4"
)
・
・
src/main/scalaディレクトリにHelloWorld.scalaがあります。これを使ってもいいですし、自分でscalaファイルを追加してもかまいません。 Slickの動作確認をするための次のようなクラスを記述しましょう。
package com.example.slicksample
import scala.slick.jdbc._
import scala.slick.driver.MySQLDriver.simple._
object Main extends App {
Database.forURL("jdbc:mysql://localhost/<DB名>?user=<ユーザー名>&password=<パスワード>",
driver = "com.mysql.jdbc.Driver") withSession {
implicit session =>
//DBアクセスコードはここへ記述
}
}
Database.forURLでユーザー名やパスワード、ドライバクラスを設定し、ブロック内でDBへアクセスするコードを記述します。 これは以前のSlickとほとんど変わりありません。(implicit部分が違うだけ) とりあえずここまでできたらsbtでrunコマンドを実行してみましょう。 とくに問題なく処理が終了すれば、準備完了です。
> run
[success] Total time: 5 s, completed 2014/02/14 14:38:01
テーブルを作成する
DBに接続することができたので、今後利用するためのテーブルを用意しましょう。 SlickではTableクラスからDDLを実行することも可能です。 まずはMainオブジェクト内に、下記のようなTableクラスを用意します。
package com.example.slicksample
import scala.slick.ast.BaseTypedType
import scala.slick.jdbc._
import scala.slick.driver.MySQLDriver.simple._
import scala.slick.lifted.Tag
import java.sql.Timestamp
object Main extends App {
class Book(tag: Tag) extends Table[(Int, String)](tag, "book") {
def id = column[Int]("id", O.PrimaryKey)
def title = column[String]("title")
def * = (id, title)
}
class Sales(tag: Tag) extends Table[(Int, Int, Int, Option[Timestamp])](tag, "sales") {
def id = column[Int]("id", O.PrimaryKey)
def bookId = column[Int]("bookId")
def num = column[Int]("num")
def date = column[Option[Timestamp]]("date")
def * = (id, bookId, num, date)
def book = foreignKey("sales_ibfk_1", bookId, TableQuery[Book])(_.id)
}
val books = TableQuery[Book]
val sales = TableQuery[Sales]
・
・
BookとSalesがそれぞれMySQLの「book」「sales」テーブルと対応します。 Tableクラスの定義方法はSlick2.0で変更された部分です。 以前はTableクラスはobjectとして定義していましたが、2.0はclassとして定義します。 また、Tagクラスをコンストラクタ引数として受け取るように定義します。
ではDDLを実行しましょう。下記例では、一度book,salesテーブルを削除してから改めて作成しています。
Database.forURL("jdbc:mysql://localhost/<DB名>?user=<ユーザー名>&password=<パスワード>",
driver = "com.mysql.jdbc.Driver") withSession {
implicit session =>
try {
(sales.ddl ++ books.ddl).drop
} catch {
case e:Exception => println("table not found")
}
(books.ddl ++ sales.ddl).create
・
・
プログラムを実行したらmysqlのコマンドラインツールで確認してみましょう。 PKや外部キーも含めて、テーブルが作成されています。
% mysql -u<ユーザー名> -p
mysql> use <DB名>
mysql> show tables;
+-----------------+
| Tables_in_mydb |
+-----------------+
| book |
| sales |
+-----------------+
3 rows in set (0.00 sec)
mysql> desc book;
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| title | varchar(254) | NO | | NULL | |
+-------+--------------+------+-----+---------+-------+
2 rows in set (0.01 sec)
mysql> desc sales;
+--------+-----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-----------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| bookId | int(11) | NO | MUL | NULL | |
| num | int(11) | NO | | NULL | |
| date | timestamp | YES | | NULL | |
+--------+-----------+------+-----+---------+-------+
4 rows in set (0.01 sec)
テーブルが作成できました。次回はテーブルに対していろいろと操作してみます。