15

我是 Scala 的新手,一直在努力解决问题,看不到如何将查询结果返回给调用方法

我有一个简单的 UserDto

case class UserDto(val firstName:String,
  val lastName:String,
  val userName:String,
  val isAdmin:Boolean) {}

用户表对象

object User extends Table[(String, String, String, Boolean)]("USER") {

  def firstName = column[String]("FIRST_NAME")
  def lastName = column[String]("LAST_NAME")
  def userName = column[String]("USER_NAME")
  def admin = column[Boolean]("IS_ADMIN")

  def * = firstName ~ lastName ~ userName ~ admin

}

和一个查询类

class UserQuerySlickImpl(dataSource:DataSource) {

  def getResults(userName:String):Option[UserDto] = {
    var resultDto:Option[UserDto] = None

    Database.forDataSource(dataSource) withSession {
      val q = for {u <- User if u.userName is userName}
      yield (u.firstName, u.lastName, u.userName, u.admin)

      for (t <- q) {
        t match {
          case (f:String, l:String, u:String, a:Boolean) => 
            resultDto = Some(new UserDto(f, l, u, a))
        }
      }
    }
    resultDto
  }
}

我可以查询数据库并获取与用户名匹配的用户,但我可以弄清楚如何返回该用户的唯一方法是在Database.forDataSource....{}.

有没有更好的方法不使用 var 而是resultDto直接返回。

还有一种方法可以UserDto直接从第一个构建理解,而不是需要第二个 for (t <- q) ...

我正在使用 slick_2.10.0-M7,版本 0.11.1。

4

2 回答 2

9

q是一个查询,而不是一个结果列表。的存在foreach在这方面可能有点令人困惑,但要获得 a Listof 结果,您需要先做q.list。这为您提供了诸如此类map的方法foldLeft

如果您想在 中获得单个/第一个结果Option,请使用q.firstOption. 一旦你有了它,你就可以map在生成的 'Option[(...)]` 上使用你的函数来将元组转换为所需的 DTO。

另一种方法是指定一个自定义映射,该映射通过使用<>运算符自动将您的结果元组映射到某个案例类,请参阅http://slick.typesafe.com/doc/0.11.2/lifted-embedding.html#tables

case class User(id: Option[Int], first: String, last: String) 

object Users extends Table[User]("users") {
  def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
  def first = column[String]("first")
  def last = column[String]("last")
  def * = id.? ~ first ~ last <> (User, User.unapply _)
}
于 2012-11-02T17:28:54.627 回答
9

我还没有玩弄过 Slick,但如果它是合理的(我的意思是与 Scala 约定一致)你应该能够做类似的事情

def getResults(userName:String):Option[UserDto] =
  Database.forDataSource(dataSource) withSession {
    val q = for {u <- User if u.userName is userName}
      yield (u.firstName, u.lastName, u.userName, u.admin)

    q.firstOption map { case (f, l, u, a) => UserDto(f, l, u, a) }
  }

如果qList[(String, String, String, Boolean)].

清理一下,你可以写

def getResults(userName:String):Option[UserDto] =
  Database.forDataSource(dataSource) withSession {
    (for (u <- User if u.userName is userName)
      yield UserDto(u.firstName, u.lastName, u.userName, u.admin)).firstOption
  }

否则,您应该可以使用

q foreach { 
   case (f, l, u, a) => return Some(UserDto(f, l, u, a))
}
return None

一般来说,return应该避免使用这样的语句,因此希望q's 类型可以为您提供更实用的功能。

于 2012-10-27T05:57:29.217 回答