技術をかじる猫

適当に気になった技術や言語、思ったこと考えた事など。

PostgreSQLにサクっとつないでみる。

環境は、sbt0.7.7, scala2.9.1 で作成。
Projectの設定にザクッと以下を流し込む。

  val posgresDriver = "postgresql" % "postgresql" % "9.0-801.jdbc4"
  val squeryl = "org.squeryl" %% "squeryl" % "0.9.4"

で、update かけたら以下のようなDatabaseModelマップクラスを作る。

package org.rex.database.core

import org.squeryl.KeyedEntity

case class Member(val id:Long,
              val userName:String,
              val email:String,
              val hashedPasswprd:String,
              val permissionId:Long) extends KeyedEntity[Long]

で、スキーマを書く。

package org.rex.database.core

import org.squeryl.Schema
import org.squeryl.PrimitiveTypeMode._

object IndexSchema extends Schema {

  val members = table[Member]("member")

  on(members)(u => declare(
    u.id is(primaryKey, autoIncremented),
    u.email is(unique, indexed("indexEmailAddresses")),
    u.hashedPasswprd is(dbType("varchar(64)")),
    u.userName is(unique, indexed)
  ))
}

データベース接続設定はこんな感じで。

package org.rex.service.core

import org.squeryl._
import org.squeryl.PrimitiveTypeMode._
import java.sql.DriverManager
import org.squeryl.adapters.PostgreSqlAdapter
import org.rex.common.ApplicationComfigure
import org.rex.database.Database

class IndexService {

  Class.forName("org.postgresql.Driver")
    SessionFactory.concreteFactory = Some(() =>
      Session.create(DriverManager.getConnection(
        "jdbc:postgresql://localhost:5432/xxxxx",
        "postgres_username",
        "postgres_password"),
      new PostgreSqlAdapter)
    )

  def bindDatabaseSession = SessionFactory.newSession.bindToCurrentThread
}

scalatra から呼ぶ時、とりあえずこうしとけば困らなかった(正しい方法かどうか不明。誰か援護ヨロ)。

  val indexService = new IndexService

  get("/") {
    indexService.bindDatabaseSession
    /* something */
  }

ことのついでに初期化からInsertまで。

val indexService = new IndexService
indexService.bindDatabaseSession

transaction {
	Database.drop
	Database.create
	val password = Utils.createMD5String("password".getBytes)
    Database.members.insert(new Member(
      1, "admin", "administrator@hogehoge.org", password, 1
    ))
}

追記

他のURLごとに呼ぶのが面倒になったのでこうしてみた。
Matcher に引っかからないというか、他のMatcherに引っかかった場合の動作未検証。

class ApplicationRoot extends ScalatraServlet {

  val indexService = new InitializeService
  var dbConnection:Session = _

  override def contentType = {
    "text/html"
  }

  before("/*") {
    dbConnection = indexService.createConnection
    dbConnection.bindToCurrentThread
  }

  after("/*") {
    dbConnection.close
    dbConnection.unbindFromCurrentThread
  }
}