我有三个不同的Scala项目,其中一个只包含在其他两个Scala项目(以下简称库)中使用的模型。三个项目中的一个是Play Web应用程序,我想在MongoDB中保存库中的模型(代码驻留在Play应用程序中)。
所以在我的图书馆里我有以下模型:
case class MyUser(id: UUID = UUID.randomUUID(), timestamp: Instant = Instant.now, name: String)
要在我的Play应用中保留MyUser
的实例,我通常会使用此模型:
case class MyUser(var _id: Option[BSONObjectID] = None,
id: UUID,
timestamp: Instant,
name: String,
var created: Option[DateTime] = None,
var updated: Option[DateTime] = None
) extends Temporal
现在我正在寻找一种方法将我的库的MyUser
变换为我的Play应用程序中的相应类,所以我想我会做这样的事情:
case class MyUser(var _id: Option[BSONObjectID] = None,
var created: Option[DateTime] = None,
var updated: Option[DateTime] = None
) extends lib.MyUser with Temporal
但是,现在我收到以下错误:
禁止个案继承。要克服此限制,请使用提取器在非叶节点上进行模式匹配。
我想过做这样的事情:
case class MyUser(var _id: Option[BSONObjectID] = None,
user: lib.MyUser,
var created: Option[DateTime] = None,
var updated: Option[DateTime] = None
) extends Temporal
我如何以正确的方式设计?
答案 0 :(得分:2)
首先,错误告诉您的是,对于扩展的类,您不应该有case class
。关于提取器的说法基本上是,如果需要在父类上进行模式匹配(这是case
的{{1}}来自简单模式匹配),你总是可以编写自定义它的提取器。
但是,这不适用于您的情况,因为您无法更改您的lib公开case class
es。
另一个解决方案是考虑两个类之间没有继承。实际上,一个是用户的表示,而另一个是包含用户的存储单元的表示。所以看起来你提出的解决方案毕竟有一些意义。
但是,在序列化对象(在Mongo中)和JVM类中添加字段似乎很麻烦,在这种情况下,您需要始终case class
来获取mongoUser.user
来自lib.MyUser
...
一个优雅的(恕我直言)解决方案是保留此字段MyUser
,但要让您的序列化将此字段展平到BSON对象的顶层,以便序列化的user: lib.MyUser
看起来像< / p>
MyUser
好像您已经继承了{
_id: ObjectId(_),
id: 123456789abc-1234-1234-1234,
...
}
。
反序列化
现在,只要您想从Mongo获取lib.MyUser
,仅出于读取目的,您可以直接以此格式反序列化它,忽略添加的字段。但是,如果您需要对其进行一些更新,则必须将其反序列化为lib.MyUser
,以便能够更新此特定的BSON文档。
scala用法
如果您将对象反序列化为MyUser
(例如,更新),您可能仍希望轻松访问MyUser
中公开的所有字段,而无需访问字段{{ 1}}每一次。这可以通过隐式转换来完成。
<强>概括强>
顺便说一下,你可以通过一般的方式对任何你想要序列化的对象做这个......
总结一下
lib.MyUser