Slick 2.0を使ってみる#1 セットアップ

2014.02.19

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)

テーブルが作成できました。次回はテーブルに対していろいろと操作してみます。

参考サイトなど