yamashiro0110の日記

yamashiro0110の日記です。おもにIT技術のメモを綴っていきます(^o^)

PlayFramework2.3(scala)でDBアクセスをするときのめも


Play + ScalaでDBアクセスのめも


環境

  • Play2.3

  • Scala 2.10.2

  • MySQL 5.6

    • 今回利用したテーブルとデータは、事前に手動で作成ずみ

DDLは↓

本来はEvolutionを利用して作るものだけど、今回は直接作成した・・・

CREATE TABLE `user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `mail` varchar(255) NOT NULL,
  `password` varchar(255) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `mail_UNIQUE` (`mail`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8

設定

SQLアクセスをするために、anormを使う

build.sbtの設定

必要なライブラリを追加

jdbc, anorm, "mysql" % "mysql-connector-java" % "5.1.34"

libraryDependencies ++= Seq(
  jdbc,
  anorm,
  cache,
  ws,
  "mysql" % "mysql-connector-java" % "5.1.34"
)

application.confの設定

DB接続設定の追加 それぞれ以下の変数は自分の環境に適宜変更する

HOSTNAME, SCHEMANAME, USERNAME, PASSWORD

db.default.driver=com.mysql.jdbc.Driver
db.default.url="jdbc:mysql://_HOSTNAME_/_SCHEMANAME_"
db.default.user="_USERNAME_"
db.default.password="_PASSWORD_"

実装

Scalaの場合、Javaと違ってモデルを扱うためのライブラリがないみたい

Slickというライブラリが時期バージョンでデフォルトになるとかならないとか・・・

初めはSlickを試していたけどうまく動いてくれなかったので断念して、 anormを利用してみたところ使い勝手が良かったのでanormを利用することにした

モデルは、Javaと同様にapp/models以下に作成していく

anormではモデルを作成するパッケージなどに特に縛りはなく、 コントローラにSQLを書いたりしても問題ないが、アレだと思うのでapp/models以下に作成していく

実際のソース

https://github.com/yamashiro0110/Play-ScalaSample/blob/master/app/models/User.scala


ハマった点.1: ~って何?

~については、以下のページに解説があった

http://libro.tuyano.com/index3?id=1069003&page=5 ここでの「~」という記号は、Anorm特有の機能で、値をリスト化する働きをします。例えば、A~B~Cとすると、((A, B), C)というようにまとめられます。こうしてまとめたものを元にMydataオブジェクトを生成するのが、その後のmap部分です。


ハマった点.2:object User.dataが何なのかよくわからない

dataについては、SQLの実行結果をオブジェクトにパースするためのものみたい

以下のコードだとSQL(SQL文).on(条件).as(パーサ.戻り値)となっている

  def findById(id: Long): Option[User] = {
    DB.withConnection { implicit c =>
      val sql = "SELECT * FROM user WHERE id = {id}"
      SQL(sql)
        .on("id" -> id)
        .as(User.data.singleOpt)
    }
  }

戻り値をOption[User]にしたのは、指定されたIDがテーブルに存在しない場合にエラーが発生したため

パーサ(data)からOption[User]を取得するためには、singleOptを呼び出せばいい

Userを取得したい場合は、singleでいける


Userモデルを呼び出している部分はapp/controllers/SampleControllerになっている

変数usrに、IDが1のUserを探して代入、存在しない場合はUser.notFoundを代入している

レスポンスはCall SampleController index!! ->という文字列にusr.nameを追加して返しているだけ

  def index = Action {
    val usr = User.findById(1).getOrElse(User.notFound)
    Ok("Call SampleController index!! -> " + usr.name)
  }

Play + JavaのEbeanがクソ便利だったので、 Play + Scalaにはなかったことを知ったとき(とSlickを断念したとき)はJavaに戻ろうかと考えたけど、 anormもなかなか使いやすかったので今後もPlay + Scalaを利用していきたいと思った

あと、今回のソースをGitHubに上げました^^;

github.com


参考にしたページm(__)m

ScalaDatabase

Model(モデル)を使ってデータベースアクセスする[Scala編](1/7):Herokuで始める 初心者のためのPlay Framework入門

Scala Optionメモ(Hishidama's Scala Option Memo)

stackoverflow.com