根据源代码,您的Votable
类型应该是以下之一:Range、Seq、Set、Map、Option、AnyVal、String、BigDecimal、Date、Time、Enumeration、Tuple1-22 或案例类。看看./src/main/scala/sorm/mappings/MappingKind.scala
详情。这是一个片段:
sealed trait MappingKind
object MappingKind {
case object Enum extends MappingKind
case object Entity extends MappingKind
case object Value extends MappingKind
case object Tuple extends MappingKind
case object OptionToTable extends MappingKind
case object OptionToNullable extends MappingKind
case object Seq extends MappingKind
case object Set extends MappingKind
case object Map extends MappingKind
case object Range extends MappingKind
def apply
( reflection : Reflection )
: MappingKind
= reflection match {
case _
if reflection <:< Reflection[scala.Range]
=> Range
case _
if reflection <:< Reflection[collection.Seq[_]]
=> Seq
...
case _
if (reflection <:< Reflection[Tuple1[_]])
|| (reflection <:< Reflection[Tuple2[_, _]])
|| (reflection <:< Reflection[Tuple3[_, _, _]])
...
|| (reflection <:< Reflection[Tuple22[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _]])
=> Tuple
case _
if reflection.isCaseClass
=> Entity
case _
=> throw new SormException("Unsupported type: " + reflection)
}
}
支持的数据类型doc。
那里使用的反射测试是./src/main/scala/sorm/reflection/Reflection.scala
:
def isCaseClass
= s match {
case s : ClassSymbol => s.isCaseClass
case _ => false
}
问题Votable
在于它不是任何这些列出类型的子类型。因此 Scala 不能确保 的子类Votable
是兼容的子类型 a MappingKind
。换句话说,不能保证你不会这样做:class A extends Votable
Sorm 不能序列化,然后它会在运行时爆炸。
现在问题很清楚了,所以我们想例如创建Votable
一个案例类并从中继承另一个案例类,但由于违反平等,这在 Scala 中是不允许的。Scala 中也没有统一的类型将某物标记为案例类。
例如,试图伪造“案例类类型”失败:
scala> trait Votable
defined trait Votable
scala> case class Comment(b: String) extends Votable
defined class Comment
scala> def isCaseClassOrWhat_?(v: AnyRef): Boolean = {
| import reflect.runtime.universe._
| val typeMirror = runtimeMirror(v.getClass.getClassLoader)
| val instanceMirror = typeMirror.reflect(v)
| val symbol = instanceMirror.symbol
| symbol.isCaseClass
| }
isCaseClassOrWhat_$qmark: (v: AnyRef)Boolean
scala> isCaseClassOrWhat_?(new Votable {});
res0: Boolean = false
scala> isCaseClassOrWhat_?(Comment("df"));
res1: Boolean = true
scala> trait VotableCaseClass extends Product with Serializable
defined trait VotableCaseClass
scala> isCaseClassOrWhat_?(new VotableCaseClass { def canEqual(that: Any): Boolean = ???; def productArity: Int = ???; def productElement(n: Int): Any = ??? });
res2: Boolean = false
如果我没看错的话,从 Scala 编译器代码中我只能理解这isCaseClass
是通过编译器CASE
在类上设置标志并isCaseClass
测试该标志的存在来实现的。
我不知道如何解决这个特殊问题。也许 Storm 可以为此提供另一个案例/标记界面。它可能是结构类型检查或Product with Serializable
类似的东西。也许可以用 Scala 宏来做到这一点——我对它们还不太了解。
编辑:
您可以使用一种Map
类型进行序列化并将案例类转换为Map
这样的:
def caseClassToMap(cc: Product): Map[String,Any] = {
val fields = cc.getClass.getDeclaredFields.map(_.getName)
fields.zip(cc.productIterator.to).toMap
}
scala> case class A(a: Int)
defined class A
scala> caseClass2Map(A(123))
res14: scala.collection.immutable.Map[String,Any] = Map(a -> 123)
我没有测试它是否适用于 SORM。