成らぬは人の為さぬなりけり

エンジニアライフをエンジョイする為のブログ

ORMを使う - Squeryl

最近Scala勉強してます。

仕事ではここ半年以上ずっと、Railsなので、
ScalaではPlayを使ってみようと思い、始めました。

ただ、ことDBアクセスに関してはPlay標準のAnormは、なんかしっくりこない、、、
ActiveRecord的な感覚で使えるORMは無いものか、と。

色々探した結果、「Squeryl」を使う事にしました。
※読み方がわかりません。ご存知の方教えてください。すくえりる?すくーりる?すくいれる?

以下、Play上でSquerylを使えるようにする手順です。
※今回はこちらを参考にさせて頂きました : Play 2.0 & squeryl simple integration

■環境

OS: MacOSX 10.7.3
Scala : 2.9.1
Play: 2.0
Squeryl: 0.9.5


1.sbt使ってるので、sbtでquerylを入れる

project/Build.scalaに以下のように追記(DBはMySQLを使います)

import sbt._
import Keys._
import PlayProject._

object ApplicationBuild extends Build {

    val appName         = "play_sample"
    val appVersion      = "1.0-SNAPSHOT"

    val appDependencies = Seq(
      "org.squeryl" %% "squeryl" % "0.9.5",
      "mysql" % "mysql-connector-java" % "5.1.18"
    )

    val main = PlayProject(appName, appVersion, appDependencies, mainLang = SCALA).settings(
      // Add your own project settings here
    )

}

※IntelliJIDEAを使っている場合は、ここでplayコンソールから

update
idea

を実行する。


2.GlobalSettingsのonStartでゴニョる

import play.api._
import play.api.db._
import org.squeryl.{Session, SessionFactory}
import org.squeryl.adapters.MySQLAdapter

object Global extends GlobalSettings {
  override def onStart(app: Application) {
    SessionFactory.concreteFactory = Some( () => connection )
    def connection() = {
      Session.create(DB.getConnection()(app), new MySQLAdapter)
    }
  }
 }

アダプターはその他にも

  • DB2Adapter
  • DerbyAdapter
  • H2Adapter
  • MySQLAdapter
  • MySQLInnoDBAdapter
  • OracleAdapter
  • PostgreSqlAdapter

があるようです。
たしか、MySQL5.5からInnoDBがデフォルトになったんでしたっけ?
だとすると、MySQLInnoDBAdapterを使うべきかも、、、

3.モデルクラス作成

app/models/User.scala

package models

case class User(var name: String,
                var email: String,
                var password: String) extends BaseEntity {
  def this() = this("", "", "")
}

app/models/Schema.scala

package models

import org.squeryl.KeyedEntity

class BaseEntity extends KeyedEntity[Long] {
  val id: Long = 0
}

4.Repository的なオブジェクトを作成

app/models/Schema.scala

...
import org.squeryl.Schema

object CoreSchema extends Schema {
  val users = table[User]("user")

  on(users)(ent => declare(
    ent.id is(autoIncremented),
    ent.email is(unique, dbType("varchar(255)"))
  ))
}

以上、で準備完了です。

実際に使ってみます。

...
  def submitEntry = Action {implicit request =>
    userForm.bindFromRequest.fold(
      errors => BadRequest(views.html.entry(errors)),
      user => {
        inTransaction {
          CoreSchema.users.insert(user)
          Redirect(routes.UserController.showEntry(user.id))
        }
      }
    )
  }

  def showEntry(id: Long) = Action {implicit request =>
    inTransaction {
      val user = CoreSchema.users.where(u => u.id === id).single
      Ok(views.html.result(user))
    }
  }

基本的に、inTransactionのブロック内でアクセスします。(もしくはtransaction)(これらのメソッドはエイリアス的な感じになってるのかな??)
(そうしないと怒られました)
必ずトランザクション張るんでしょうか?
selectのみでもinTransactionというのは非常に違和感がありますね。

  • inTranscationとtranscationは全く同じなのか
  • 必ずトランザクションを張らないとイケないのか?(更新系の処理時のみになっているのか)

などは、これから要調査です。

よし、次はAjaxやってみて、その次はPjaxのサンプルを作ってみることにします。