我是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。
是否有更好的方法不使用var但直接返回resultDto
。
还有一种方法可以直接从第一个构造UserDto
进行理解,而不是需要第二个用于(t < - q)......
我使用的是slick_2.10.0-M7,版本0.11.1。
答案 0 :(得分: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) }
}
这正是q
为List[(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
的类型可以为你提供更实用的功能。
答案 1 :(得分:9)
您的q
是查询,而不是结果列表。在这方面,foreach
的存在可能会有点混乱,但要获得List
结果,您需要先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 _)
}