First question:
It is not possible to avoid passing around the Session
in some way.
The implicit Session
you pass around is not some global information of your application. The Session
object represents the current open session you have with the database. With Play Slick, this database session is opened for you when a request is made to a DBAction
.
That means that your Session
is only available, and strictly tied to, an HTTP request. In fact, you'll find that it is a field of the implicit request =>
you note in every DBAction
:
val someAction = DBAction { implicit request => // DBAction opens database session, and puts it in request.dbSession
// Database session for this request is implicitly available on
// the scope here and therefore may be passed to other methods implicitly
} // Database session is closed
So you have a new and different database session for every request. Furthermore, every database interaction requires a database session. Therefore, every method that executes some query therefore needs to be provided with the current Session
you have for processing your particular request.
The reason implicits are usually used for this is because it provides the cleanest code for passing around this session.
// With implicits
def helperMethod1(param: Any)(implicit s: Session) = someQuery1.list // Session is passed implicitly
def helperMethod2(param: Any)(implicit s: Session) = someQuery2.exists.run // Session is passed implicitly
def action = DBAction { implicit request =>
// Stuff
helperMethod1(param1) // request.dbSession is passed implicitly
// Stuff
helperMethod2(param2) // request.dbSession is passed implicitly
// Stuff
}
Versus the more repetitive
// Without implicits
def helperMethod1(param: Any, s: Session) = someQuery.list(s) // Must pass Session explicitly
def helperMethod2(param: Any, s: Session) = someQuery.exists.run(s)
def action = DBAction { implicit request =>
val session = request.dbSession
// Stuff
helperMethod1(param1, session) // Have to repeat session for every DB call
// Stuff
helperMethod2(param2, session)
// Stuff
}
The example in the Slick documentation question that @cvogt mentions is not a good solution to your problem, as it does not reduce the amount of arguments you need to pass around in this case.
Second question:
In general, Session
is a so-called type alias for for JdbcBackend#Session
. That means that type Session = JdbcBackend#Session
, i.e. they're exactly the same. You can safely use Session
in any code except, unfortunately, Play controller code.
The reason for this is that Play controllers also define a type Session
. Play's Session
represents the current HTTP session, based on the cookies the user has set. Unfortunately, this naming clashes with Slick's Session
.
To work around this, you can alias the import: import scala.slick.driver.JdbcProfile.simple.{Session => SlickSession}
.