我有一个关于Slick/Scala的有趣问题,我希望你们中的一个好伙伴可以帮助我.
我在SLICK案例类中有几个表格和扩展名
case class A(...)
case class B(...)
case class C(...)
Run Code Online (Sandbox Code Playgroud)
分享这些共同领域
(id: String, livemode: Boolean, created: DateTime, createdBy : Option[Account]) .
Run Code Online (Sandbox Code Playgroud)
因为在每个案例类中都重复这些字段,所以我想探索将它们提取到单个对象或类型中的可能性.
但是,在创建SLICK表对象时,我希望最终包含这些公共字段的位置,以便我可以在每个表中保留它们各自的值.
object AsTable extends Table[A]("a_table") {
...
def id = column[String]("id", O.PrimaryKey)
def livemode = column[Boolean]("livemode", O.NotNull)
def created = column[DateTime]("created", O.NotNull)
def createdBy = column[Account]("created_by", O.NotNull)
...
}
Run Code Online (Sandbox Code Playgroud)
实际上,我正在寻找的最终结果是允许我更改公共字段而无需更新每个表.
有没有办法做到这一点?
提前致谢
gzm*_*zm0 18
我没试过这个,但是你混入的特性怎么样:
trait CommonFields { this: Table[_] =>
def id = column[String]("id", O.PrimaryKey)
def livemode = column[Boolean]("livemode", O.NotNull)
def created = column[DateTime]("created", O.NotNull)
def createdBy = column[Account]("created_by", O.NotNull)
protected common_* = id ~ livemode ~ created ~ createdBy
}
Run Code Online (Sandbox Code Playgroud)
然后你可以这样做:
object AsTable extends Table[(String,Boolean,DateTime,Account,String)]("a_table")
with CommonFields {
def foo = column[String]("foo", O.NotNull)
def * = common_* ~ foo
}
Run Code Online (Sandbox Code Playgroud)
你现在唯一需要重复的是元素的类型.
UPDATE
如果要进行对象映射,请执行以下操作:
做就是了:
case class A(
id: String,
livemode: Boolean,
created: DateTime,
createdBy: Account,
foo: String)
object AsTable extends Table[A]("a_table") with CommonFields {
def foo = column[String]("foo", O.NotNull)
def * = common_* ~ foo <> (A.apply _, A.unapply _)
}
Run Code Online (Sandbox Code Playgroud)
这似乎是最经济的解决方案(而不是试图限定*
在CommonFields
和添加型参数).但是,如果字段发生更改,则需要更改所有案例类.
我们可以尝试通过在案例类上使用组合来缓解这种情况:
case class Common(
id: String,
livemode: Boolean,
created: DateTime,
createdBy: Account)
case class A(
common: Common,
foo: String)
Run Code Online (Sandbox Code Playgroud)
但是,在构造映射器函数时,我们(某处)最终必须转换表单的元组:
(CT_1, CT_2, ... CT_N, ST_1, ST_2, ..., ST_M)
Run Code Online (Sandbox Code Playgroud)
CT
常见类型(已知CommonFields
)
ST
特定类型(已知AsTable
)
至:
(CT_1, CT_2, ... CT_N), (ST_1, ST_2, ..., ST_M)
Run Code Online (Sandbox Code Playgroud)
为了通过它们单独子程序转换Common
和A
,并从他们的元组.
我们必须在不知道CT
(实施时AsTable
)或ST
(实施时CommonFields
)的数量或确切类型的情况下这样做.Scala标准库中的元组无法执行此操作.您需要使用无形的HLists
提供的示例来执行此操作.
这是否值得付出是值得怀疑的.
基本轮廓可能看起来像这样(没有所需的所有隐含的混乱).这段代码不会像这样编译.
trait CommonFields { this: Table[_] =>
// like before
type ElList = String :: Boolean :: DateTime :: Account :: HNil
protected def toCommon(els: ElList) = Common.apply.tupled(els.tupled)
protected def fromCommon(c: Common) = HList(Common.unapply(c))
}
object AsTable extends Table[A] with CommonFields {
def foo = column[String]("foo", O.NotNull)
def * = common_* ~ foo <> (x => toA(HList(x)), x => fromA(x) tupled)
// convert HList to A
protected def toA[L <: HList](els: L) = {
// Values for Common
val c_els = els.take[Length[ElList]]
// Values for A
val a_els = toCommon(c_els) :: els.drop[Length[ElList]]
A.apply.tupled(a_els.tupled)
}
// convert A to HList
protected def fromA(a: A) =
fromCommon(a.common) :: HList(A.unapply(a)).drop[One]
}
Run Code Online (Sandbox Code Playgroud)
使用更多类型的魔法你可以解决最后两个问题:
toA
并fromA
到基底性状(通过在性状使用类型参数,或者使用抽象类型成员)ElList
从中提取来明确定义Common.apply
归档时间: |
|
查看次数: |
2189 次 |
最近记录: |