我会举个例子。
假设我有三个像这样定义的表:
(伪代码)
Realm
id: number, pk
name: text, not null
Family
id: number, pk
realm_id: number, fk to Realm, pk
name: text, not null
Species
id: number, pk
realm_id: number, fk to Family (and therefore to Realm), pk,
family_id: number, fk to Family, pk,
name: text, not null
一个临时案例类定义将是
case class Realm (
id: Int,
name: String
)
case class Family (
id: Int,
realm: Realm,
name: String
)
case class Species (
id: Int,
family: Family,
name: String
)
如果我在查询数据库后创建了一个json,它将如下所示:
SELECT *
FROM realm
JOIN family
ON family.realm_id = realm.id
JOIN species
ON species.family_id = family.id
AND species.realm_id = family.realm_id
示例数据:
[{
"id": 1,
"family": {
"id": 1,
"name": "Mammal",
"realm": {
"id": 1,
"name": "Animal"
}
},
"name": "Human"
},
{
"id": 2,
"family": {
"id": 1,
"name": "Mammal",
"realm": {
"id": 1,
"name": "Animal"
}
},
"name": "Cat"
}]
好的,到目前为止......这是可用的,如果我需要显示按领域分组的每个物种,我会转换JsValue或在javascript中进行过滤等。但是当将数据发布回服务器时,这些类似乎有点尴尬。如果我想添加一个新物种,我必须发布这样的东西:
{
"id": ???,
"family": {
"id": 1,
"name": "Mammal", // Awkward
"realm": {
"id": 1,
"name": "Animal" // Awkward
}
},
"name": "Cat"
}
我的课程应该是:
case class Realm (
id: Int,
name: Option[String]
)
case class Family (
id: Int,
realm: Realm,
name: Option[String]
)
case class Species (
id: Option[Int],
family: Family,
name: String
)
像这样,我可以省略发布看似不必要的数据,但是类定义并不反映数据库中不可为空的字段。
查询是数据的投影。更多或类似Table.map(function) => Table2
。当从数据库中提取数据并且我没有得到名称字段时,并不意味着它是null。你是如何处理这件事的?
答案 0 :(得分:0)
处理它的一种方法是使用其他数据结构来表示互连,而不是让每个级别了解下一个数据结构。
例如,在您需要表示整个树的位置,您可以用以下代码表示:
Map[Realm, Map[Family, Seq[Species]]]
然后在某些地方只有Realm
,例如作为REST / JSON资源,在某些地方你可能(Species, Family, Realm)
只想与一个物种合作,但需要了解另外两个物种等级中的等级。
我还建议你考虑让你的模型结构定义你的JSON结构两到三次,当你在你的模型类中更改任何时,使用JSON的代码会发生什么? (如果你真的想要这个,你真的需要通过模型结构,为什么不直接从数据库结果构建你的JSON并跳过一级数据转换?)