2

以下是代码:

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 中重构这个的想法?

4

2 回答 2

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在对 DB 调用进行包装,而是在获得结果之后进行包装。数据库调用将是阻塞的主要来源,而不是数据库结果的处理。您应该考虑在未来包装 DB 调用

于 2015-03-03T10:30:05.090 回答
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))

可能有一些错误,因为您的代码不可运行并且我无法编译它。

于 2015-03-03T10:11:24.200 回答