How to convert query result to case class?

2019-06-24 00:02发布

问题:

I'm using Slick 2.0 and I have the following User case class:

case class User(id: Option[Long], email: String, password: String)

class Users(tag: Tag) extends Table[User](tag, "user") {
  def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
  def email = column[String]("email")
  def password = column[String]("password")

  def * = (id.?, email, password) <> ((User.apply _).tupled, User.unapply _)
}

and I have the following function getting a user via their database id:

def findOneById(id: Long) = DB.withSession { implicit session =>
  val result = (for {
                  u <- users if u.id === id
                } yield (u.id, u.email, u.password)).first
  User(Option(result._1), result._2, result._3)
}

Is there an easier way to convert the Seq response back result into the User case class?

回答1:

Ok, I found my answer. I got it in part from @benji and in part from this post: Converting scala.slick.lifted.Query to a case class.

Instead of using a for comprehension, the following returns an Option[User], which is exactly what I need:

def findOneById(id: Long):Option[User] = DB.withSession { implicit session =>
  users.filter(_.id === id).firstOption
}


回答2:

For comprehension is easier in use with sql joins. Example:

def findOneById(id: Long) = DB.withSession { implicit session =>
    val query = for {
        u <- users if u.id === id
        t <- token if t.user_id = u.id && token.isActive === `A`
        } yield u    
    query.firstOption
}


回答3:

To convert the result to list of User case class, you can simply do

result.map(User.tupled)

However, that I will only work, if your data model is consitent. For example: Your user case class has id as optional where as it is a primary key in the DB which is wrong.



标签: slick-2.0