Statistical Programming

Slick実装例

Slickを使った実装例。

今回はTypesafeが提供しているActivatorを利用しながら開発してみる

Slick

Typesafe Activator – Typesafe Reactive Platform - Typesafe

まずはActivatorをダウンロードし、フォルダの中にあるactivatorファイルをクリック。

しばらく待つと自動的にブラウザを起動しactivatorに移動。

好きなテンプレートを選ぶ(ここではHello Slick)。

まずはSlickとembedded databasesもしくは外部データベース用のドライバーをプロジェクトに加える必要があるため

First of all, you need to add Slick and te embedded databases or drivers for external databases to your project.

 

 

build.sbtを開き以下のようにlibrary dependenciesを追加する

 

libraryDependencies ++= List(

  "com.typesafe.slick" %% "slick" % "1.0.1",

  "org.slf4j" % "slf4j-nop" % "1.6.4",

  "com.h2database" % "h2" % "1.3.166"

)

SlickはSLF4Jをデバッグのログ用に使っているのでそれも追加している。

Slick uses SLF4J for its own debug logging so you also need to add an SLF4J implementation. Here we are using slf4j-nop to disable logging. You have to replace this with a real logging framework likeLogback if you want to see log output.

src/main/scala/Hello.scalaを開き以下をimportする。

// Use H2Driver to connect to an H2 database
import scala.slick.driver.H2Driver.simple._

// Use the implicit threadLocalSession 

import Database.threadLocalSession

 SlickはデータベースとしてH2を利用しているのでここではSlickのH2Driverをimportしている。H2.Driver.simple._は一般的に必要となるであろう機能をだいたい詰まってるからこれだけしてたらシンプルなものはおk。もうひとつのimportはセッション管理を簡単にするためのものでこれをimportしておけば現在のスレッドにセッションをattachすることができ、細かい管理を自分がしなくて済むらしい。

Since we are using H2 as our database system, we need to import features from Slick's H2Driver. A driver's simple object contains all commonly needed imports from the driver and other parts of Slick such as session handling. The only extra import we use is thethreadLocalSession. This simplifies the session handling by attaching a session to the current thread so you do not have to pass it around on your own (or at least assign it to an implicit variable).

 次にmainの役割を果たす objects Hello extends Appを作成しそのbodyの中でデータベースのコネクションとセッションを作成。

 

Database.forURL("jdbc:h2:mem:test1", driver = "org.h2.Driver") withSession {
  // The session is never named explicitly. It is bound to the current
  // thread as the threadLocalSession that we imported
}



In a Java SE environment, database sessions are usually created by connecting to a JDBC URL using a JDBC driver class (see the JDBC driver's documentation for the correct URL syntax). If you are only using plain SQL queries, nothing more is required, but when Slick is generating SQL code for you (using the direct embedding or thelifted embedding), you need to make sure to use a matching Slick driver (in our case the H2Driver import above).
 

それではスキーマ(データベースの構造)を定義していく。 Suppliersクラス、CoffeesクラスはTableを継承しておりその中の引数の左側 [ ] はそれぞれの列のScalaでのデータ型を記述し、後ろの ( ) にはSQLテーブルの名前を記述。列の定義は必ずdefで行い、通常のscalaの値や関数を作成したい場合にはvalを利用。defによけいな者を入れるとおかしくなるから要注意。def宣言し列の名前を決めたらcolumnメソッドで列のScalaデータ型とSQLの名前を引数として渡してやる。基本的にこの2つがあれば十分だけどidのように重複を許したくない場合はO.PrimaryKey(0じゃなくてO)を引数として渡すことで重複を防ぐことが出来る。def  * はProjection定義(projectionとはfunctionでありinputとしてデータベースの関係性を受け取り条件に合う関係性をoutputする)。中身はクラスで定義した型と一致しなければならない。基本的に。

   

class Suppliers extends Table[(Int,String)]("SUPPLIERS"){

        def id=column[Int]("SUP_ID",O.PrimaryKey)

        def name=column[String]("SUP_NAME")

        def *  =id~name

    }

 

    val Suppliers=new Suppliers

 

    class Coffees extends Table[(String,Int,Double)]("COFFEES"){

        def name=column[String]("COF_NAME",O.PrimaryKey)

        def supID=column[Int]("SUP_ID")

        def price=column[Double]("PRICE")

        def * =name~supID~price

        def supplier=foreignKey("SUP_FK",supID,Suppliers)(_.id)

        

    }

    val Coffees=new Coffees

 ちなみにforeighKeyとはデータベースに制約を加えるもので、この例ではCoffeeの中のsupIDはSuppliersのidと一致しなければいけないというもの。逆は真じゃない。

The foreignKey definition in the Coffees table ensures that thesupID field can only contain values for which a corresponding idexists in the Suppliers table, thus creating an n to onerelationship: A Coffees row points to exactly one Suppliers row but any number of coffees can point to the same supplier. This constraint is enforced at the database level.

その2に続く…