【问题标题】:firstOption showing error in slick 3.0 and play 2.4firstOption 在 slick 3.0 和 play 2.4 中显示错误
【发布时间】:2015-09-09 21:14:59
【问题描述】:

我在我的项目中集成了剪影(securesocial 的一个分支)作为身份验证库,所以我正在关注它的示例项目,其中包含 slick play-silhouette-slick-seed

在写 these lines 时,我在 eclipse 中遇到很多错误。

def find(loginInfo: LoginInfo) = {
  DB withSession { implicit session =>
    Future.successful {
      slickLoginInfos.filter(
        x => x.providerID === loginInfo.providerID && x.providerKey === loginInfo.providerKey
      ).firstOption match {
        case Some(info) =>
          slickUserLoginInfos.filter(_.loginInfoId === info.id).firstOption match {
            case Some(userLoginInfo) =>
              slickUsers.filter(_.id === userLoginInfo.userID).firstOption match {
                case Some(user) =>
                  Some(User(UUID.fromString(user.userID), loginInfo, user.firstName, user.lastName, user.fullName, user.email, user.avatarURL))
                case None => None
              }
            case None => None
          }
        case None => None
      }
    }
  }
}

[预计会出现错误,因为示例项目是使用旧版本的 play 和 slick 编写的]

我尝试迁移它们,因此我将 withSession 替换为 run 并将 firstOption 替换为 headOption ,因为我在 slick 官方文档中读到以前的那些在 slick 3.0 中已被弃用。以下是我的更改,但仍然无法正常工作

def find(loginInfo: LoginInfo) = {
   DB run { 
     Future.successful {
        slickLoginInfos.filter(
          x => x.providerID === loginInfo.providerID && x.providerKey === loginInfo.providerKey
        ).result.headOption match {
          case Some(info) =>
            slickUserLoginInfos.filter(_.loginInfoId === info.id).result.headOption match {
              case Some(userLoginInfo) =>
                slickUsers.filter(_.id === userLoginInfo.userID).result.headOption match {
                  case Some(user) =>
                    Some(User(UUID.fromString(user.userID), loginInfo, user.firstName, user.lastName, user.fullName, user.email, user.avatarURL))
                  case None => None
                }
              case None => None
            }
          case None => None
        }
     }
  }
}

我是新手和 scala,每天都在探索新事物。你能帮我解决这些错误吗?如果有人也可以向我解释未来值的使用,我们使用 Await (db.run(....)) 获得的正常值有什么好处,以及如何解析未来对象中的值,因为我在某些地方看到他们使用地图和他们使用 onSuccess 或案例的一些地方,这非常令人困惑。处理未来价值观的最佳方式是什么?

【问题讨论】:

    标签: scala playframework slick securesocial


    【解决方案1】:

    查找joinLeft,如果没有任何匹配项,它将使用Option 表示右侧(joinRight 表示左侧)。所以,你会想要这样的东西:

    val q1 = for {
      (loginInfo, userLoginInfo) <- slickLoginInfos.filter(...) joinLeft slickUserLoginInfos on (_.id === _.loginInfoId)
    } yield (loginInfo, userLoginInfo)
    val q2 = for {
      ((loginInfo, userLoginInfo), user) <- q1 joinLeft slickUsers.filter(...) on (_._2.loginInfoId === _.id)
    } yield {
       // use loginInfo, userLoginInfo and user are optional
    }
    

    userLoginInfouser 将有 OptionSomeNone,这取决于是否有任何匹配。您在其上运行 q2headOption 以获得整体结果。

    期货

    以前,您会执行以下操作:

    dao.fetch().map(_.toString)
    

    其中dao.fetch() 返回Seq[Int]。现在,使用 Slick 3.0,这将是 Future[Seq[Int]],这意味着您只需要另一个 .map(或 flatMap):

    dao.fetch().map(_.map(_.toString))
    

    除了现在包裹在Future 中之外,它继续执行与以前相同的操作。使用Futures 的好处在于,您无需为每次调用数据库而阻塞线程。

    【讨论】:

    • 我们不能不使用连接吗?同样在查询 q2 我有点不清楚在 slickUsers.filter(.....) 里面写什么
    • 在这种情况下,您每次都需要 db.run() (只是 .result 不会这样做,除非您加入)。这样做的缺点是你会进行三个单独的数据库调用,而加入你只会做一个数据库调用。
    • 谢谢,我知道它会很慢。但是请您帮我完成第二个查询。我只是被困在这里,因为 _._2 是一种我无法在其中应用 === 运算符的选项。我正在学习 slick 对此了解不多。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-29
    • 2015-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-17
    相关资源
    最近更新 更多