在提升映射中包含另一个案例类

时间:2014-01-01 05:54:47

标签: slick

我希望在使用SLICK提升映射时将富类型(案例类)作为另一个成员包含在内。我不确定如何。

这是我到目前为止所拥有的。 (它遵循cake pattern for multiple DB support)。

trait ChallengeComponent { this: Profile with UserComponent with GameComponent =>
  import profile.simple._

  class Challenges(tag: Tag) extends Table[Challenge](tag, "challenges") {
    def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
    def challengerId = column[String]("challenger_id")
    def * = (id, challengerId) <> (constructChallenge, extractChallenge)
    def challenger = foreignKey("challenger_fk", challengerId, users)(_.gPlusId)
  }

  private def constructChallenge(id: Option[Int], challengerId: String) =
    Challenge(id, user(challengerId).get)
  private def extractChallenge(c: Challenge) = (c.id, c.challenger.id)

  ...
}

case class Challenge(id: Option[Int], challenger: User)

其中UsersComponent特征定义为:

trait UserComponent { this: Profile =>
  import profile.simple._

  class Users(tag: Tag) extends Table[User](tag, "users") {
    def id = column[String]("id", O.PrimaryKey)
    def displayName = column[String]("display_name", O.NotNull)
    def * = (gPlusId, displayName)
  }
  val users = TableQuery[Users]

  def user(gPlusId: String)(implicit session: Session): Option[User] =
    users.filter(_.id === id).firstOption

问题是在尝试构建Session时没有可用的隐式User

将一种类型嵌入另一种类型的可行模式是什么?最好是以懒惰的方式,但不会用持久性代码污染案例类。

1 个答案:

答案 0 :(得分:2)

使用*投影无法做到这一点。您需要直接映射到表的案例类:

case class User(id: String, displayName: String)
case class Challenge(id: Option[Int], challengerId: String)

class Users(tag: Tag) extends Table[User](tag, "users") {
  def id = column[String]("id", O.PrimaryKey)
  def displayName = column[String]("display_name", O.NotNull)
  def * = (id, displayName) <> (User.tupled, User.unapply)
}

class Challenges(tag: Tag) extends Table[Challenge](tag, "challenges") {
  def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
  def challengerId = column[String]("challenger_id")
  def * = (id, challengerId) <> (Challenge.tupled, Challenge.unapply)
}

然后在你的例子中,你真正追求的是一个连接2个表的查询:

def getChallengeAndChallenger(id: Int): Option[(Challenge, User)] = db withSession {
  implicit session =>
    val q = for {
      c <- challenges if c.id === id
      u <- users if u.id === c.challengerId
    } yield (c, u)
    q.firstOption
}

当然,如果愿意,您可以将元组替换(映射)到另一个案例类。