1

Play 2.2 を使用して Scala でアプリケーションを作成しています。play-slick 0.5.0.8MySQL DB コネクタとして使用しています。次のアプリケーションコントローラーがあります。

package controllers

import models._
import models.database._

import play.api._
import play.api.mvc._
import play.api.Play.current
import play.api.db.slick._

object Application extends Controller {
  // WORKS:
  def test = DBAction {
    implicit session => Ok(views.html.test(Cameras.findById(1)))
  }

  // DOES NOT WORK:
  def photo = Action {
    val p = PhotoFetcher.fetchRandomDisplayPhoto(someParametersBlah))
    Ok(views.html.photo(p))
  }
}

ご覧のとおり、testDBAction は機能し、DB から写真を正常に取得できます。残念ながら、photoアクションは機能しません。

PhotoFetcher.fetchRandomDisplayPhoto(blah)はたくさんの異なることをします。その内部に埋め込まれているのは への呼び出しで、オブジェクトCameras.findById(blah)を返す必要があります ( DBAction で動作します)。ただし、この構成では次のエラーが発生します。Cameratest

could not find implicit value for parameter s: slick.driver.MySQLDriver.simple.Session

photo次のように、アクションを DBAction にしようとしました。

def photo = DBAction {
  implicit session => {
    val p = PhotoFetcher.fetchRandomDisplayPhoto(someParametersBlah))
    Ok(views.html.photo(p))
  }
}

しかし、それは同じセッションの欠落エラーになります。PhotoFetcher が暗黙的なセッションを認識していないようです。

私が試したもう1つのことは、にインポートslick.session.Database.threadLocalSessionすることPhotoFetcherですが、次のエラーのみが発生します。

SQLException: No implicit session available; threadLocalSession can only be used within a withSession block

それが助けになる場合、これは私のCamerasオブジェクトの簡略化されたバージョンです:

package models.database

import models.Format.Format
import scala.slick.driver.MySQLDriver.simple._

case class Camera(id: Long,
                  otherStuff: String)

trait CamerasComponent {
  val Cameras: Cameras

  class Cameras extends Table[Camera]("cameras") {
    def id          = column[Long]("id", O.PrimaryKey, O.AutoInc)
    def otherStuff  = column[String]("otherStuff", O.NotNull)

    def * = id ~ otherStuff <> (Camera.apply _, Camera.unapply _)

    val byId         = createFinderBy(_.id)
    val byOtherStuff = createFinderBy(_.otherStuff)
  }
}

object Cameras extends DAO {
  def insert(camera: Camera)(implicit s: Session) { Cameras.insert(camera) }
  def findById(id: Long)(implicit s: Session): Option[Camera] = Cameras.byId(id).firstOption
  def findByOtherStuff(otherStuff: String)(implicit s: Session): Option[Camera] = Cameras.byOtherStuff(model).firstOption
}

というわけで、どこかでズレてしまったようです。現在、DAO オブジェクトに Controller DBAction から直接アクセスすることのみが可能であり、別のクラス内からはアクセスできません。どんな助けでも大歓迎です。ありがとう!

4

1 に答える 1

5

あなたの定義はPhotoFetcher.fetchRandomDisplayPhoto.fetchRandomDisplayPhoto暗黙的なセッションを取りますか?

 // PhotoFetcher
 def fetchRandomDisplayPhoto(args: Blah*)(implicit s: Session) = {
   // ...
   val maybeCam = Cameras.findById(blah) // <- sees the implicit session 
   // ...
 }

threadLocalsessionまたは、 in に依存していPhotoFetcherますか? ( の暗黙的なセッション引数がないfetchRandomDisplayPhoto)?

Slick の threadLocalSession は、何かをすばやく試すのに便利ですが、後で混乱したり、わかりにくくなったりする可能性があります。Slick モデルを呼び出すすべてのメソッドに対して、明示的な(implicit s: Session)パラメーター リストを使用することをお勧めします。これは ともうまく機能しDBAction、フレームワークがセッションを管理できるようにします。

欠点は(implicit s: Session)、すべてのメソッドを使用する必要があることです。次のような回避策があります: https://github.com/freekh/play-slick/issues/20

Scala は冗長ではなく、リファクタリングに非常に適しています。そのため、この橋に到達したときにその橋を渡ることを検討し、DBActionデータベースに関するすべてのアクションに使用することをお勧めします。データベースモデルを呼び出すすべてのメソッドに暗黙的なセッションを与え、それがどれだけのマイレージをもたらすかを確認してください。

于 2013-10-21T10:45:49.357 に答える