【问题标题】:Scala & Slick: type mismatch with [Product with Serializable] needs to be fixedScala & Slick:与 [Product with Serializable] 的类型不匹配需要修复
【发布时间】:2023-03-14 07:39:01
【问题描述】:

我正在尝试通过重用基于 userID 检索单个用户的方法来实现检索所有用户的方法,但无法确定类型不匹配。你能告诉我如何解决这个问题吗?

UserDAOImpl.scala:

def findAll: Future[Seq[User]] = {
  val dbUsers: Future[Seq[DbUser]] = db.run(users.result)

  dbUsers.map { dbUserSeq =>
    dbUserSeq.map { dbUser => find(UUID.fromString(dbUser.userID)).value.get match {
      case Success(Some(usr: User)) => usr
      case _ => None
    }}
  }
}

我将省略find 的定义,因为它可以正常工作,但这里是签名。

def find(userID: UUID): Future[Option[User]] = {

错误信息:

found   : Seq[Product with Serializable]
required: Seq[models.User]
          dbUserSeq.map { dbUser =>
                        ^

以防万一,用户的定义

private val users = TableQuery[UserTable]

任何建议将不胜感激。

【问题讨论】:

  • 这似乎与 slick 无关,而仅与您的代码有关。 ffind(UUID.fromString(dbUser.userID)) 返回一个未来,所以你可能需要平面图?
  • 您已经拥有了所有用户,不是吗?在这里 val dbUsers: Future[Seq[DbUser]] = db.run(users.result)
  • @Edmondo1984 case Success(Some(usr: User)) => usr 部分做到了。不过感谢您的回复。
  • @Artavazd Balayan Future[Seq[User]] not Future[Seq[DbUser]] 是我所需要的。

标签: scala playframework slick


【解决方案1】:

非阻塞方法:

def findAll: Future[Seq[User]] = {
  db.run(users.result)
    .map(dbUserSeq =>
      Future.sequence(dbUserSeq.map(dbUser => find(UUID.fromString(dbUser.userID))))
    )
    .flatMap(userFutSeq => // userFutSeq is a Future[Seq[Option[User]]]
      userFutSeq.map(userSeq => userSeq.collect { case Some(u) => u })
    )
}

上面的代码收集找到的用户并忽略其余的。

避免使用Await,除非用于测试目的。使用期货时,请留在Future 的上下文中。

【讨论】:

  • 感谢您的精彩提示。我知道使用 Await 不是一个好主意,但是没有它,我不知道怎么做。只是一件事:您发布的代码实际上没有编译,说“value flatten is not a member of scala.concurrent.Future[scala.concurrent.Future[Seq[models.User]]],也许之前缺少分号‘价值趋于平缓’?”但是如果我用 flatMap 替换地图,它会编译。你知道是什么原因造成的吗?
  • @hirofujitaaki:您可能会遇到错误,因为您使用的是 Scala 的 2.12 之前的版本; flatten 已添加到 Scala 2.12 中的 Future API。话虽如此,flatMap 是更好的方法,所以我更新了答案。
  • 好的,所以我不应该那么担心。感谢您的帮助!
【解决方案2】:

之前的代码其实有几个问题,下面的代码就是我目前想出的解决方案。也许不是最简单的,但它确实有效。

  def findAll: Future[Seq[User]] = {
    db.run(users.result).map { dbUserSeq =>
      dbUserSeq.map { dbUser =>
        val userFut: Future[Option[User]] = find(UUID.fromString(dbUser.userID))
        Await.ready(userFut, Duration.Inf).value.get match {
          case Success(Some(usr: User)) => usr
          case _ => throw new RuntimeException
        }
      }
    }
  }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-20
    • 2014-09-26
    • 1970-01-01
    • 2015-04-03
    • 2015-04-09
    • 1970-01-01
    • 2016-07-28
    • 2021-09-25
    相关资源
    最近更新 更多