"right" 在 Play Framework 中使用写 Slick 3.0 Scala 查询的方法
The "right" way to use write Slick 3.0 Scala queries in Play Framework
我正在使用 Slick 3.0,并且(当然)几乎所有的例子都涵盖了 Slick 2.x。事情发生了变化,坦率地说,看起来 更多 复杂,而不是更少。
举个例子:我想通过id获取一个对象(一个GPPerson)。这就是我现在所拥有的,它似乎 非常 冗长......比 Slick 2.x:
def get(id: GPID): Option[GPPerson] = Await.result(
db.run(
people.filter(_.id === id).result), Duration.Inf
).headOption
在 Slick 2.x 中,由于隐式等原因,事情变得更容易了。不过以上好像是我想出的最简洁的表达了。
它也没有真正解决异常处理,我需要添加它。
你可以做到这一点。
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 }
我几个月前开始在一个新项目中使用Slick 3.0,我也有同样的疑问。我是这样理解的:
Slick 3.0 专为非阻塞异步(反应式)应用程序而设计。显然,它现在意味着 Akka + Play / Spray。在这个世界上,您主要与 Futures 互动,这就是为什么 Slick 的 db.run returns Future。使用 Await.result 没有意义 - 如果您需要阻塞调用,最好使用 return 到 2.x。
但是,如果您使用反应式堆栈,您将立即受益。例如,Spray 是完全非阻塞的库,可以使用 onComplete 指令很好地与 Futures 配合使用。您可以在 Spray 路由中使用 Slick 的结果调用 returns Future 的方法,然后将该结果与 onComplete 一起使用。在这种情况下,整个响应-回复管道是非阻塞的。
您还提到了异常处理,所以这正是您的做法 - 使用 Futures。
所以根据我的经验,我会按照以下方式编写您的方法:
def get(id: GPID): Future[Option[GPPerson]] = db.run(
people.filter(_.id === id).result.map(_.headOption)
)
然后与 Future 一起工作。
我正在使用 Slick 3.0,并且(当然)几乎所有的例子都涵盖了 Slick 2.x。事情发生了变化,坦率地说,看起来 更多 复杂,而不是更少。
举个例子:我想通过id获取一个对象(一个GPPerson)。这就是我现在所拥有的,它似乎 非常 冗长......比 Slick 2.x:
def get(id: GPID): Option[GPPerson] = Await.result(
db.run(
people.filter(_.id === id).result), Duration.Inf
).headOption
在 Slick 2.x 中,由于隐式等原因,事情变得更容易了。不过以上好像是我想出的最简洁的表达了。
它也没有真正解决异常处理,我需要添加它。
你可以做到这一点。
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 }
我几个月前开始在一个新项目中使用Slick 3.0,我也有同样的疑问。我是这样理解的:
Slick 3.0 专为非阻塞异步(反应式)应用程序而设计。显然,它现在意味着 Akka + Play / Spray。在这个世界上,您主要与 Futures 互动,这就是为什么 Slick 的 db.run returns Future。使用 Await.result 没有意义 - 如果您需要阻塞调用,最好使用 return 到 2.x。
但是,如果您使用反应式堆栈,您将立即受益。例如,Spray 是完全非阻塞的库,可以使用 onComplete 指令很好地与 Futures 配合使用。您可以在 Spray 路由中使用 Slick 的结果调用 returns Future 的方法,然后将该结果与 onComplete 一起使用。在这种情况下,整个响应-回复管道是非阻塞的。
您还提到了异常处理,所以这正是您的做法 - 使用 Futures。
所以根据我的经验,我会按照以下方式编写您的方法:
def get(id: GPID): Future[Option[GPPerson]] = db.run(
people.filter(_.id === id).result.map(_.headOption)
)
然后与 Future 一起工作。