LiftのDBをMySQLに

liftのデフォルトではDerbyが動いてますが、MySQLに切り替える。あと、development環境/test環境でのデータベース切り替え、specsの実行。Liftコンソール。

MySQLとspecsのライブラリをsbtに登録しておく。

 import sbt._
 class MyProject(info: ProjectInfo) extends DefaultWebProject(info)
 {
  val lift = "net.liftweb" % "lift-core" % "1.1-M6" % "compile"
  val jetty6 = "org.mortbay.jetty" % "jetty" % "6.1.19" % "test"
  val servlet = "javax.servlet" % "servlet-api" % "2.5" % "provided"
  val mysql = "mysql" % "mysql-connector-java" % "5.1.6" % "runtime"
  val junit = "junit" % "junit" % "4.5" % "test"
  val specs = "org.scala-tools.testing" % "specs" % "1.6.0" % "test"
  val smackRepo = "m2-repository-smack" at "http://maven.reucon.com/public"
 }

書き換えたら、必要なjarをかき集めておきます。

 C\myproject>sbt update


Lift1.0のDB設定

こんな感じでConnectionManagerを書いていました。

■/src/main/scala/bootstrap/liftweb/Boot.scala

 DB.defineConnectionManager(DefaultConnectionIdentifier, MySQLVendor)

 object MySQLVendor extends ConnectionManager {
  def newConnection(name: ConnectionIdentifier): Box[Connection] = {
   try {
    Class.forName("com.mysql.jdbc.Driver")
    val dm = DriverManager.getConnection("jdbc:mysql://localhost/db?user=xxx&password=xxx")
    Full(dm)
   } catch {
    case e : Exception => e.printStackTrace; Empty
   }
  }
  def releaseConnection(conn: Connection) {conn.close}
 }


Lift1.1の場合は、propertiesファイルで指定する流儀

■/src/main/resources/default.props

   db.driver=com.mysql.jdbc.Driver
   db.url=jdbc:mysql://localhost/db
   db.user=xxxxx
   db.password=xxxxx

プロパティファイルの名称は、環境で切り替えられるようになっていて、

運用モード[run.mode=production] → production.default.props
テストモード[run.mode=test] → test.default.props
開発モード[run.mode=_] → default.props

などで切り替えます。run.modeは、JVM環境変数(-Drun.mode=testなど)です。
指定しなければ、開発モードでdefaults.propsを参照します。

その他、OSユーザー毎、マシン毎にプロパティファイルを書き換えることができます。net.liftweb.util.PropsのAPIリファレンスを参照。ちなみにDB以外の情報でも使えます。


モデル作ってspecs実行まで

■/src/main/scala/myproject/model/Product.scala

  package myproject.model
  import _root_.net.liftweb.mapper._
  import _root_.net.liftweb.util._
  class Product extends LongKeyedMapper[Product] with IdPK {
    def getSingleton = Product
    object name extends MappedString(this, 255)
  }
  object Product extends Product with LongKeyedMetaMapper[Product]{
    override def dbTableName = "products"
    def findByName(name:String) = findAll(By(Product.name,name))
  }

を作ったら、Bootstrapでboot時にテーブルスキーマを生成するように登録しておきます。

  val models = List( User, Product )
  Schemifier.schemify(true, Log.infoF _, models:_* )

■/src/test/scala/myproject/model/ProductTest.scala

  package myproject.model
  import org.specs._
  import org.specs.matcher._
  import org.specs.specification._

  object ProductTestSpecs extends Specification {
    "Product" should {
     "be available" in {
      (new bootstrap.liftweb.Boot).boot
      Product.count must notBeNull
     }
    }
  }

実行すると、bootを呼んだときに、Productに対応するテーブルをCREATEしてくれます。

  C\myproject> sbt
  > test
  [info] == myproject.model.ProductTestSpecs ==
  INFO - CREATE TABLE products (id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE KEY ,name VARCHAR(255)) ENGINE = InnoDB
  [info] == test-finish ==
  [info] Run: 1, Passed: 1, Errors: 0, Failed: 0
  [info] All tests PASSED.
  [success] Successful.
  [info] Total time: 4 s

さすがにexample毎にbootするのはアレなので、specsフレームワークのもっと上位のフックで準備しておけばよいでしょう。

LiftConsoleの使い方

  C:\myproject> mvn scala:console -DmainConsole=LiftConsole
  scala> import myproject.model._
  scala> Product.create.name("scala gum").save
  scala> Product.findAll

などと、コンソール上でモジュールの動作を確認できます。
※今日教えていただいたScalaTohoku、yuroyoroさん、ありがとうございました!


Railsなどでお馴染みの機能はだいたいそろってますね。


コメント

コメントしてください
お名前:
入力しなければ「匿名さん」。20字以内。

メール:
入力しても表示しません

URL:
入力すればリンクが貼れます


コメント: