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
scala slick query return value
提问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)].
如果q是List[(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。这就给了你喜欢的方法map和foldLeft等。
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 _)
}

