scala 圆滑的查询返回值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13097492/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 04:40:30  来源:igfitidea点击:

scala slick query return value

scalaslick

提问by Doug Anderson

I am rather new at Scala and have been struggling with slick and can't see how to return the results of a query to the calling method

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

I have a simple UserDto

我有一个简单的 UserDto

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

a User table object

一个用户表对象

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

}

and a query class

和一个查询类

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
  }
}

I can query the database and get the user that matches the username, but the only way I could figure out how to return that user is by creating a var outside of the Database.forDataSource....{}.

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

Is there a better way that does not use the var but returns the resultDtodirectly.

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

also is there a way to construct the UserDtodirectly from the first for comprehension rather than needing the second for (t <- q) ...

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

I am using slick_2.10.0-M7, version 0.11.1.

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

回答by Aaron Novstrup

I haven't toyed with Slick yet but if it's reasonable (by which I mean consistent with Scala conventions) you should be able to do something like

我还没有玩弄 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) }
  }

This is exactly what you would do if qwas a List[(String, String, String, Boolean)].

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

Cleaning this up a bit, you can write

清理一下,你可以写

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
  }

Otherwise, you should be able to use

否则,您应该可以使用

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

Generally, returnstatements like this one should be avoided, so hopefully q's type gives you something more functional to work with.

一般来说,return应该避免这样的语句,所以希望q的类型为您提供更多功能性的东西。

回答by eriksensei

Your qis a query, not a list of results. The presence of foreachmight be a little confusing in that respect, but to obtain a Listof results, you need to do q.listfirst. That gives you methods like mapand foldLeftand so on.

q是查询,而不是结果列表。的存在foreach在这方面可能有点令人困惑,但要获得 aList的结果,您需要先做q.list。这就给了你喜欢的方法mapfoldLeft等。

If you want to get a single/the first result in an Option, use q.firstOption. Once you have that, you can mapyour function over the resulting 'Option[(...)]` to transform the tuple into the desired DTO.

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

An alternative way would be to specify a custom mapping that automatically maps your result tuples to some case class by using the <>operator, see http://slick.typesafe.com/doc/0.11.2/lifted-embedding.html#tables:

另一种方法是指定一个自定义映射,通过使用<>运算符自动将您的结果元组映射到某个 case 类,请参阅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 _)
}