Scala 我应该创建特征来表示模型的枚举值吗?
假设我有一个这样的模型:Scala 我应该创建特征来表示模型的枚举值吗?,scala,slick,Scala,Slick,假设我有一个这样的模型: case class User( id: Int, name: String, userType: Int) 我是否应该这样做: sealed trait UserType case object Member() extends UserType case object Anonymous() extends UserType 我还应该为每个用户类型关联一个值 然后,我会将User case类更改为具有UserType属性,而不是int 我想接下来我会为sl
case class User(
id: Int,
name: String,
userType: Int)
我是否应该这样做:
sealed trait UserType
case object Member() extends UserType
case object Anonymous() extends UserType
我还应该为每个用户类型关联一个值
然后,我会将User case类更改为具有UserType属性,而不是int
我想接下来我会为slick创建一个隐式转换器,我相信它是一个从int到UserType的MappedColumnType
更新
这是用于使用slick db访问的。我会用另一种方法。根据扩展
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
然后在需要时对实际的用户
类型进行模式匹配。我选择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
)
然后可以在User
案例类中使用userType:userType
。
在表定义中,可以有def userType=column[userType](“用户类型”)
更新
选择enum而不是trait的原因之一是,如果不显式放置超类型,slick无法找到此隐式转换器。
例如
屈服
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对象时存在一些问题。您需要做的是:
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
sealed trait UserType {
val code: Int
// I added field below
val base: UserType = this
}
UserTable
.filter(_.userType === Member.base)
.result
这正是@Michal Tomanski所指出的。你可以做一些小把戏来让它变得平滑一点
只需修改您的特征,如下所示:
UserTable
.filter(_.userType === (Member :: UserType))
.result
sealed trait UserType {
val code: Int
// I added field below
val base: UserType = this
}
UserTable
.filter(_.userType === Member.base)
.result
然后您可以进行如下查询:
UserTable
.filter(_.userType === (Member :: UserType))
.result
sealed trait UserType {
val code: Int
// I added field below
val base: UserType = this
}
UserTable
.filter(_.userType === Member.base)
.result
它可能比铸造稍好一些
除此之外-我会遵循@Michal Tomanski的答案(使用枚举
),假设它对您的案例足够(也许带有特征
/案例对象
s的解决方案更灵活,但另一方面,您需要做更多的管道,正如在这个答案中可以看到的那样)。抱歉,这是一个灵活的解决方案,我将强调这一点,而不仅仅是圆滑的标签。重复这一点: