假设我有一个模型,如下所示:
case class User(
id: Int,
name: String,
userType: Int)
那么我应该这样做吗:
sealed trait UserType
case object Member() extends UserType
case object Anonymous() extends UserType
我还应该以某种方式为每个用户类型关联一个值。
然后我会将用户案例类更改为具有 UserType 属性而不是 int?
我想然后我会为slick创建一个隐式转换器,我相信这将是从int到UserType的MappedColumnType。
更新这是为了使用光滑的数据库访问。
我会反过来做。我会根据扩展User
的情况为用户提供一种类型:
sealed trait User
case class NormalUser(name: String, id: Int) extends User
case class SuperUser(name: String, id: Int, superPowers: Map[String, String]) extends User
然后在需要时与实际User
类型进行模式匹配。
我会选择枚举:
object UserType extends Enumeration {
type UserType = Value
val Member = Value("Member")
val Anonymous = Value("Anonymous")
}
正如您所说,转换器:
implicit val userTypeColumnType = MappedColumnType.base[UserType, String](
userType => userType.toString,
UserType.withName
)
然后,您可以在User
案例类中使用userType: UserType
。在表定义中,您可以有def userType = column[UserType]("user_type")
更新选择枚举而不是 trait 的原因之一是,当您不显式放置超类型时,slick 无法找到此隐式转换器。例如
.filter(_.userType === Member)
收益 率
type mismatch;
[error] found : Member.type
[error] required: slick.lifted.Rep[?]
[error] .filter(_.userType === Member).result
但以下作品
.filter(_.userType === Member.asInstanceOf[UserType])
.filter(_.userType === (Member : UserType))
正如下面提到的@Michal Tomanski - 使用 trait
/case object
s 时存在某些问题。您需要做的是:
sealed trait UserType {
val code: Int
}
case object Member extends UserType {
override val code: Int = 0
}
case object Anonymous extends UserType {
override val code: Int = 1
}
object UserType {
def byId(id: Int): UserType = id match {
case Member.code => Member
case Anonymous.code => Anonymous
case _ => throw new IllegalArgumentException("...")
}
}
implicit val enumColumnType = MappedColumnType.base[UserType, Int](
e => e.code,
i => UserType.byId(i)
)
上面将允许您执行这样的查询:
UserTable
.filter(_.userType === (Member :: UserType))
.result
这正是托曼斯基@Michal指出的。但是,您可以做一些小技巧来平滑一点。
只需像这样修改您的特征:
sealed trait UserType {
val code: Int
// I added field below
val base: UserType = this
}
然后你可以像这样查询:
UserTable
.filter(_.userType === Member.base)
.result
它可能比铸造稍微好一点。
除此之外 - 我会遵循 Tomanski @Michal答案(使用 Enumeration
(,假设它足以满足您的情况(也许使用 trait
/case object
s 的解决方案更灵活,但另一方面,您需要做更多的管道,如本答案所示(。