【问题标题】:In Slick 3.0, how to simplify nested `db.run`?在 Slick 3.0 中,如何简化嵌套的 `db.run`?
【发布时间】:2015-05-12 09:05:06
【问题描述】:

我使用的是 Slick 3.0,以下是我的代码:

def registerMember(newMember: TeamMember): Future[Long] = {

  db.run(
    teamProfileTable.filter(u => u.ID === newMember.ID).result.headOption
  ).flatMap {
    case None => Future(-1)
    case _ => db.run(
      (teamProfileTable returning teamProfileTable.map(_.staffID)) += newMember.toTeamRecord
    )
  }
}

这看起来不错。但是当回调层数较多时,代码可能会变得难以阅读。我尝试使用for-expressionandThen 来简化代码。但是由于模式匹配部分,我只能使用flatMap 来实现这个..

有人对如何重构这个有想法吗?

【问题讨论】:

  • 您应该组合查询,然后仅作为最后一步在数据库上运行组合。这就是我认为它应该工作的方式。如果您添加更多代码来制作可运行的示例,我可以尝试给出答案。
  • @pagoda_5b 谢谢!但是,如果第二个查询取决于第一个查询的结果,如何组合这两个查询呢?我认为andThen 不适合这里..
  • @hanfeisun 您可能应该使用 for comprehensions,但如果您不能提供一些自洽代码进行测试,我将无法进一步帮助您。除非您更明确,否则我可能只会猜测您的代码的意图和结果。 :)

标签: scala slick slick-3.0


【解决方案1】:

我认为这里的理解应该没问题,您只需要在第一个Future 的结果中对Option 进行条件处理。这样的东西应该可以工作(注意我没有编译检查这个):

def registerMember(newMember: TeamMember): Future[Long] = {

  for{
    r1Opt <- db.run(teamProfileTable.filter(u => u.ID === newMember.ID).result.headOption
    r2 <- r1Opt.fold(Future.successful(-1L))(r1 => db.run((teamProfileTable returning teamProfileTable.map(_.staffID)) += newMember.toTeamRecord)
  } yield r2

}

您可以在fold 的右侧看到,如果它是Some(如r1),我可以访问第一个Future 的结果。

我什至会更进一步,为 for 理解的步骤创建单独的方法来清理内容,如下所示:

def registerMember(newMember: TeamMember): Future[Long] = {
  def findMember = 
    db.run(teamProfileTable.filter(u => u.ID === newMember.ID).result.headOption

  def addMember(r1Opt:Option[TeamMember]) = {
    r1Opt.fold(Future.successful(-1L)){r1 =>
      db.run((teamProfileTable returning teamProfileTable.map(_.staffID)) += 
        newMember.toTeamRecord)
    }
  }

  for{
    r1Opt <- findMember
    r2 <- addMember(r1Opt)
  } yield r2

}

【讨论】:

    【解决方案2】:

    当查询跨越两个表时,在 Slick 3.0 中简化嵌套 db.runs 的另一种方法是将查询连接到单个查询中。 Joining and Zipping。但是,OP 似乎在同一个表上嵌套查询的情况比较少见,因此这种方法在这种特定情况下可能没有帮助。

    val query = slickLoginInfos join slickUserLoginInfos on 
       ((l,ul) => l.id === ul.loginInfoId) 
    db.run((for { (l, ul) <- query } yield (ul)).result.headOption)
    

    【讨论】:

      猜你喜欢
      • 2015-10-06
      • 1970-01-01
      • 2015-12-01
      • 1970-01-01
      • 2015-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-26
      相关资源
      最近更新 更多