我希望在使用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
。
将一种类型嵌入另一种类型的可行模式是什么?最好是以懒惰的方式,但不会用持久性代码污染案例类。
答案 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
}
当然,如果愿意,您可以将元组替换(映射)到另一个案例类。