在Slick 3.0中,如何简化嵌套的`​​db.run`?

时间:2015-05-12 09:05:07

标签: scala slick slick-3.0

我正在使用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来实现此功能。

有没有人有关于如何重构这个的想法?

2 个答案:

答案 0 :(得分:2)

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

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的右侧看到我有权访问第一个Future的结果,如果它是Somer1)。

我甚至会更进一步,为理解的步骤创建单独的方法来清理,例如:

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

}

答案 1 :(得分:0)

当查询跨越两个表时,在Slick 3.0中简化嵌套db.runs的另一种方法是将查询连接到单个查询中。 Joining and Zipping。但是,OP似乎在同一个表上有一些不太常见的嵌套查询,所以这种方法在特定情况下可能没有用。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="300dp"
    android:layout_height="match_parent">

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="0.7">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:text="A"
            android:id="@+id/textView2"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:text="AAA"
            android:id="@+id/textView4"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:text="AAAAA"
            android:id="@+id/textView5"/>
    </LinearLayout>

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="0.3">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:text="B"
            android:id="@+id/textView3"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:text="BBB"
            android:id="@+id/textView6"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:text="BBBB"
            android:id="@+id/textView7"/>
    </LinearLayout>
</LinearLayout>