如何在灵活的 table 映射中省略大小写 class 字段?
How can I omit case class fields in a slick table mapping?
我正在自学一些 Scala,目前正在尝试使用 slick (3.1) + play 框架,所以这里的答案可能很简单,但我遗漏了一些明显的东西。我有以下模型和 Table
case class User(id: Long = -1,
username: String,
passwordHash: String,
email: Option[String] = None)
class Users(tag: Tag) extends Table[User](tag, "USERS") {
def id = column[Long]("ID", O.PrimaryKey, O.AutoInc)
def username = column[String]("USERNAME")
def email = column[Option[String]]("EMAIL")
def passwordHash = column[String]("PASSWD_HASH")
def * = (id, username, passwordHash, email) <>((User.apply _).tupled, User.unapply)
}
现在上面的这个工作正常了,但我想在 User
案例 class 中添加一些字段 不是 保存在USER中table,即权限和角色,像这样:
case class User(id: Long = -1,
username: String,
passwordHash: String,
email: Option[String] = None,
permissions: Seq[String] = Seq.empty,
roles: Seq[String] = Seq.empty)
这些应该作为用户 ID -> permission/role 映射(简单的一对多关系)进入各自的 tables。
最终那些也应该被查询,但现在我只想忽略额外的字段(纯粹作为练习)。如何将 table 中的原始投影调整为 omit/ignore 那些新字段?明明是原始映射
def * = (id, username, passwordHash, email) <>((User.apply _).tupled, User.unapply)
不再有效,因为元组与大小写不匹配 class。据我所知,这应该不会太难,因为 <>
只需要两个函数,从一个 touple 转换为一个 User 实例,反之亦然,这些函数应该忽略新字段(或用它们的默认值填充它们).但是我不知道怎么表达。
我尝试向 User
伴生对象添加一个带有较短签名的新 apply()
,但随后我得到一个错误,基本上告诉我 slick 不知道 apply()
到哪个 apply()
采用。有道理,但我不知道如何引用一个或另一个。我对 User
的附加构造函数做了同样的事情,结果是同样的问题。我尝试编写这样的基本转换函数:
class Users(tag: Tag) extends Table[User](tag, "USERS") {
def constructUser = (id: Long, username: String, passwordHash: String, email: Option[String]) =>
User(id, username, passwordHash, email)
def extractUser = (user: User) => user match {
case User(id, username, passwordHash, email, permissions, roles) =>
Some((id, username, passwordHash, email))
}
def id = column[Long]("ID", O.PrimaryKey, O.AutoInc)
def username = column[String]("USERNAME")
def email = column[Option[String]]("EMAIL")
def passwordHash = column[String]("PASSWD_HASH")
def * = (id, username, passwordHash, email) <>(constructUser, extractUser)
}
遗憾的是,这也会导致错误:
[error] found : (Long, String, String, Option[String]) => models.User
[error] required: ? => ?
[error] def * = (id, username, passwordHash, email) <>(constructUser, deconstructUser)
你的问题是你的 constructUser
是 4 个参数的函数,而它应该是单个 Tuple4
的函数
尝试添加类型签名。
例如,此示例有效(包括一些简化)
type Data = (Long, String, String, Option[String])
def constructUser: Data => User = {
case (id, username, passwordHash, email) => User(id, username, passwordHash, email)
}
def extractUser: PartialFunction[User, Data] = {
case User(id, username, passwordHash, email, _, _) =>
(id, username, passwordHash, email)
}
def * = (id, username, passwordHash, email) <> (constructUser, extractUser.lift)
我正在自学一些 Scala,目前正在尝试使用 slick (3.1) + play 框架,所以这里的答案可能很简单,但我遗漏了一些明显的东西。我有以下模型和 Table
case class User(id: Long = -1,
username: String,
passwordHash: String,
email: Option[String] = None)
class Users(tag: Tag) extends Table[User](tag, "USERS") {
def id = column[Long]("ID", O.PrimaryKey, O.AutoInc)
def username = column[String]("USERNAME")
def email = column[Option[String]]("EMAIL")
def passwordHash = column[String]("PASSWD_HASH")
def * = (id, username, passwordHash, email) <>((User.apply _).tupled, User.unapply)
}
现在上面的这个工作正常了,但我想在 User
案例 class 中添加一些字段 不是 保存在USER中table,即权限和角色,像这样:
case class User(id: Long = -1,
username: String,
passwordHash: String,
email: Option[String] = None,
permissions: Seq[String] = Seq.empty,
roles: Seq[String] = Seq.empty)
这些应该作为用户 ID -> permission/role 映射(简单的一对多关系)进入各自的 tables。
最终那些也应该被查询,但现在我只想忽略额外的字段(纯粹作为练习)。如何将 table 中的原始投影调整为 omit/ignore 那些新字段?明明是原始映射
def * = (id, username, passwordHash, email) <>((User.apply _).tupled, User.unapply)
不再有效,因为元组与大小写不匹配 class。据我所知,这应该不会太难,因为 <>
只需要两个函数,从一个 touple 转换为一个 User 实例,反之亦然,这些函数应该忽略新字段(或用它们的默认值填充它们).但是我不知道怎么表达。
我尝试向 User
伴生对象添加一个带有较短签名的新 apply()
,但随后我得到一个错误,基本上告诉我 slick 不知道 apply()
到哪个 apply()
采用。有道理,但我不知道如何引用一个或另一个。我对 User
的附加构造函数做了同样的事情,结果是同样的问题。我尝试编写这样的基本转换函数:
class Users(tag: Tag) extends Table[User](tag, "USERS") {
def constructUser = (id: Long, username: String, passwordHash: String, email: Option[String]) =>
User(id, username, passwordHash, email)
def extractUser = (user: User) => user match {
case User(id, username, passwordHash, email, permissions, roles) =>
Some((id, username, passwordHash, email))
}
def id = column[Long]("ID", O.PrimaryKey, O.AutoInc)
def username = column[String]("USERNAME")
def email = column[Option[String]]("EMAIL")
def passwordHash = column[String]("PASSWD_HASH")
def * = (id, username, passwordHash, email) <>(constructUser, extractUser)
}
遗憾的是,这也会导致错误:
[error] found : (Long, String, String, Option[String]) => models.User
[error] required: ? => ?
[error] def * = (id, username, passwordHash, email) <>(constructUser, deconstructUser)
你的问题是你的 constructUser
是 4 个参数的函数,而它应该是单个 Tuple4
尝试添加类型签名。
例如,此示例有效(包括一些简化)
type Data = (Long, String, String, Option[String])
def constructUser: Data => User = {
case (id, username, passwordHash, email) => User(id, username, passwordHash, email)
}
def extractUser: PartialFunction[User, Data] = {
case User(id, username, passwordHash, email, _, _) =>
(id, username, passwordHash, email)
}
def * = (id, username, passwordHash, email) <> (constructUser, extractUser.lift)