在Scala / Slick中,如何重构代码(响应拦截)?

时间:2015-03-03 09:51:46

标签: scala playframework slick slick-2.0 play-slick

以下是代码:

def find(loginInfo: LoginInfo): Future[Option[UserProfile]] = {
  val res = DB.withSession { implicit session =>
    //if loginInfo.providerID == "waylens"
    userProfileTable.filter(u => u.userName === loginInfo.providerKey).list
  }
  val size = res.size
  if (size <= 1)
    Future(res.headOption.map(userProfileRecordToUserProfile))
  else
    throw new Exception("db error")
}

def findByEmail(providerID: String, email: String): Future[Option[UserProfile]] = {
  val res = DB.withSession { implicit session =>
    //if loginInfo.providerID == "waylens"
    userProfileTable.filter(u => u.email === email && u.status === 1).list
  }
  val size = res.size
  if (size <= 1)
    Future(res.headOption.map(userProfileRecordToUserProfile))
  else
    throw new Exception("db error")
}

def findByProfileID(profileID: Long): Future[Option[UserProfile]] = {
  val res = DB.withSession { implicit session =>
    userProfileTable.filter(u => u.id === profileID).list
  }
  val size = res.size
  if (size <= 1)
    Future(res.headOption.map(userProfileRecordToUserProfile))
  else
    throw new Exception("db error")
}

这些代码多次出现,这真的很烦人

   val size = res.size
      if (size <= 1)
        Future(res.headOption.map(userProfileRecordToUserProfile))
      else
        throw new Exception("db error")

有没有人有关于在Slick中重构这个的想法?

2 个答案:

答案 0 :(得分:1)

您可以在这里轻松使用高阶函数,首先让我们从方法中获取您的查询:

lazy val a = userProfileTable.filter(u => u.userName === loginInfo.providerKey)
lazy val b = userProfileTable.filter(u => u.email === email && u.status === 1)
lazy val c = userProfileTable.filter(u => u.id === profileID)

请注意,我正在使这个懒惰,因为你还没有在范围内进行会话。

现在让我们创建一个执行此查询的函数(您可以使用类型参数使其更通用):

def executeQuery(q: ⇒ : Query[UserProfiles, UserProfiles#TableElementType]): Int = {
  db.withSession { implicit session ⇒
    q.list
  }
}

然后我们需要检查长度:

def listToUserProfile(list: List[UserProfile]): Future[Option[UserProfile]] = {
  if (list.length <= 1)
    Future(list.headOption.map(userProfileRecordToUserProfile))
  else
     throw new Exception("db error")
}

现在你可以这样做:

listToUserProfile(executeQuery(a))

可能存在一些错误,因为您的代码无法运行,我无法编译它。

答案 1 :(得分:1)

首先使用Either创建一个通用方法来执行返回未来或错误的查询


def getElement[E, U, C[_]](query: Query[E, U, C]) = {
    db.withSession { implicit session =>
        query.list.headOption match {
             case Some(ele) => Right(Future(ele))
             case None => Left(new Exception("db error"))
       }
    }
  }

现在在代码中,你可以做到


def find(loginInfo: LoginInfo): Future[Option[UserProfile]] = 
      getElement(userProfileTable.filter(u => u.userName === loginInfo.providerKey)).right.map(userProfileRecordToUserProfile)

与其他人类似:


def findByEmail(loginInfo: LoginInfo): Future[Option[UserProfile]] = 
      getElement( userProfileTable.filter(u => u.email === email && u.status === 1))).right.map(userProfileRecordToUserProfile)

另一方面,您没有将future包裹在数据库调用之上但是在获得结果之后。数据库调用将是阻塞的主要来源,而不是数据库结果的处理。您应该考虑在未来包装数据库调用