The “right” way to use write Slick 3.0 Scala queries in Play Framework

徘徊边缘 提交于 2019-12-07 03:21:00

问题


I'm using Slick 3.0 and (of course) almost all the examples out there cover Slick 2.x. Things have changed and frankly seem more complicated, not less.

Here's an example: I want to get an object (a GPPerson) by id. This is what I have right now, and it seems very verbose... more so than Slick 2.x:

def get(id: GPID): Option[GPPerson] = Await.result(
    db.run(
        people.filter(_.id === id).result), Duration.Inf
    ).headOption

In Slick 2.x things were easier because of the implicits, among other things. But the above seems to be the most concise expression I've come up with.

It also doesn't really address exception handling, which I would need to add.


回答1:


I started to use Slick 3.0 in a new project a few months ago and I had the same questions. This is what I understood:

Slick 3.0 was designed for non-blocking asynchronous (reactive) applications. Obviously it means Akka + Play / Spray nowadays. In this world you mostly interact with Futures, that's why Slick's db.run returns Future. There is no point in using Await.result - if you need blocking calls it's better to return to 2.x.

But if you use reactive stack you'll get benefits immediately. For example, Spray is completely non-blocking library that works with Futures nicely using onComplete directive. You can call a method that returns Future with a result from Slick in a Spray route and then use that result together with onComplete. In this case the whole response-reply pipeline is non-blocking.

You also mentioned exception handling, so this is exactly how you do it - using Futures.

So based on my experience I would write your method in a following way:

def get(id: GPID): Future[Option[GPPerson]] = db.run(
  people.filter(_.id === id).result.map(_.headOption)
)

and then work with a Future.




回答2:


you can do this.

def syncResult[R](action:slick.dbio.DBIOAction[R, slick.dbio.NoStream, scala.Nothing]):R = {
    import scala.concurrent.duration.Duration

    val db = Database.forConfig("db")
    try {
      Await.result(db.run(action), Duration.Inf)
    } finally db.close
  }

def get(id: GPID): Option[GPPerson] = syncResult { people.filter(_.id === id).result.headOption }


来源:https://stackoverflow.com/questions/30339825/the-right-way-to-use-write-slick-3-0-scala-queries-in-play-framework

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