说我有一个类似的模型:
case class User(
id: Int,
name: String,
userType: Int)
我应该这样做:
sealed trait UserType
case object Member() extends UserType
case object Anonymous() extends UserType
我还应该以某种方式为每个UserType关联一个值。
然后我会将User case类更改为具有UserType属性而不是int?
我想我会为光滑创建一个隐式转换器,我相信它是从int到UserType的MappedColumnType。
更新的 这是为了使用灵活的数据库访问。
答案 0 :(得分:2)
我会反过来做。我会为用户提供一种类型,具体取决于扩展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
类型进行模式匹配。
答案 1 :(得分:2)
我和enum一起去了:
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
)
然后,您可以在userType: UserType
案例类中使用User
。
在表格定义中,您可以拥有def userType = column[UserType]("user_type")
<强>更新强> 选择enum over trait的原因之一是当你没有明确地输入超类型时,光滑无法找到这个隐式转换器。 E.g。
.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))
答案 2 :(得分:1)
正如@Michal Tomanski所提到的below - 使用trait
/ case object
时存在一些问题。你需要做的是:
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 Tomanski所指出的。你可以做一些小技巧,但要稍微平滑一下。
只需修改你的特征:
sealed trait UserType {
val code: Int
// I added field below
val base: UserType = this
}
然后您可以像这样查询:
UserTable
.filter(_.userType === Member.base)
.result
它可能比铸造稍微好一点。
除此之外 - 我跟随@Michal Tomanski回答(使用Enumeration
),假设它足以满足您的需求(可能是trait
/ case object
s的解决方案更灵活,但另一方面,你需要做更多的管道工程,这可以在这个答案中看到。)