Problems with Scala Play Framework Slick Session

こ雲淡風輕ζ 提交于 2019-12-24 17:06:02

问题


I'm creating an application in Scala using Play 2.2. I'm using play-slick 0.5.0.8 as my MySQL DB connector. I have the following application controller:

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))
  }
}

As you can see, the test DBAction works, and it's able to fetch a photo from the DB just fine. Unfortunately, the photo Action does not work.

My PhotoFetcher.fetchRandomDisplayPhoto(blah) does a bunch of different things. Buried inside of it is a call to Cameras.findById(blah), which should return a Camera object (which works in the test DBAction). However, with this configuration I get the following error:

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

I have tried making the photo Action into a DBAction, like so:

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

But that just results in the same missing session error. It's like PhotoFetcher doesn't know about the implicit session.

The other thing I've tried is importing slick.session.Database.threadLocalSession in my PhotoFetcher, but that only results in the following error:

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

If it's any help, this is a simplified version of my Cameras object:

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
}

So, it seems as if I've gotten crossed-up somewhere. Right now it's only possible for me to access my DAO objects directly from a Controller DBAction, and not from inside of some different class. Any help would be appreciated. Thanks!


回答1:


Does your definition of PhotoFetcher.fetchRandomDisplayPhoto.fetchRandomDisplayPhoto take an implicit session?

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

Or are you relying on a threadLocalsession in PhotoFetcher? (no implicit session argument for fetchRandomDisplayPhoto)?

While Slick's threadLocalSession is handy for quickly trying out stuff, it can lead to confusion and loss of clarity later on. It's best to just use explicit (implicit s: Session) parameter lists for all methods that call your Slick models. This also plays well with DBAction, letting the framework manage sessions.

The downside is you have to have (implicit s: Session) on all your methods - there are workarounds like this: https://github.com/freekh/play-slick/issues/20

Scala isn't verbose and is very amenable to refactoring - so I'd recommend thinking about crossing that bridge when you come to it, and use DBAction for all actions that do database stuff; give all methods that call your database models an implicit session, and see how much that mileage that gives you.



来源:https://stackoverflow.com/questions/19488135/problems-with-scala-play-framework-slick-session

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!