【问题标题】:Solution in Slick to Map a Future[Option] DB result to a valueSlick 中将 Future[Option] DB 结果映射到值的解决方案
【发布时间】:2017-06-06 02:10:17
【问题描述】:

我在play 框架中这样做是为了使用slick 获取命令和执行表之间的关系。

class ExecutionsTable(tag: Tag) extends BaseTable[Execution](tag, "executions") {
    def name = column[String]("name")
    def execution = column[String]("execution")
    def commandId = column[Long]("command_id")
    def * = (id, name, execution, commandId) <> (Execution.tupled, Execution.unapply)
    def command = foreignKey("commands", commandId, commandsTableQ)(_.id)

    implicit val CommandToLong = MappedColumnType.base[Long, Command] (
      id => {
        val cmd = Await.result(new CommandsDAO().findById(id), 1 second)
        cmd.get
      },
      cmd => cmd.id
    )

findById 返回Future[Option[Command]] 我正在尝试使用这种方法,但我不确定它是否是最好的解决方案。

你会推荐什么?

【问题讨论】:

  • 嗯。我没有一个好的答案,但这对我来说看起来很危险。作为一般规则,Await 应该被视为 Play 内部的毒药——它破坏了线程设计,并且只有在您知道自己在做什么时才应该使用。 (而.get 有神秘崩溃的风险。)你真的需要自定义Command 类型吗?我同情对它的渴望(我假设您在这里将它用于外键关系?),但这段代码看起来可能会在生产中引起微妙的问题......
  • 我在 Slick gitter 频道中被建议不要执行此实现,因为它依赖于 Future 结果并且对于 MappedColumnType 它没有好的解决方案。我被建议做一个完整的 SQL 查询

标签: scala playframework slick


【解决方案1】:

您想处理错误吗?如果你这样做,我建议你使用 flatMap 然后再次进行模式匹配,看看你的函数是否真的返回了一些东西。给你,沿着这些思路:

val x : Future[Option[String]] = Future(Option("1"))

val id = x.flatMap(optId => optId match {
  case Some(id) => id
  case None => throw new Exception("No ID.")
}

【讨论】:

  • “无法解析带有此类签名的 flatMap” 预期 Option[Command] => Future[NotInferedS] ,实际:Option[Command] => Any
  • 你应该使用地图,而不是平面地图。
  • 但我需要在他的示例案例中返回 Command 对象“1”
  • 你可以这样做: val id = x.map { case Some(x) => x } 这样你就可以忽略任何没有的情况。这基本上就是@C4stor 所说的。干杯。
  • 这样做我得到:找到:scala.concurrent.Future[models.entities.Command] required:models.entities.Command,无法从未来获取命令
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多