这不是一个简单的问题...... SQL 数据库不擅长对类层次结构建模。
你需要一个好的 ORM。
我把一个类层次结构放在一个表中,做的是:
首先,我确保它是相关的:例如,将网络 CMS 的节点、文章等放在同一个表中是有意义的,因为这些都是同一事物的变体。
这个想法是您需要创建用于搜索、索引和进行 SQL 查询的数据库列,但您不需要将所有信息存储在数据库列中。您可以将其余部分存储在 BLOB 列中的序列化对象中。
在表中,当然有一列指示该行是哪个类的实例-一些所有类共有的“核心”列,基本上是基类字段。- 仅由某些子类使用的其他列,但我需要进行搜索,因此需要对它们进行索引 - 包含来自对象的所有其他数据的 BLOB。
基本上当我在数据库中存储一个对象时,根据其类的相关列被填充,其余数据(甚至整个对象)被推到 BLOB 中。
这样做的好处是,如果你添加一个不需要搜索或索引,只存储的成员值,你不需要将它放在数据库列中,所以你根本不需要对数据库进行任何更改:它将存储在序列化的 BLOB 中。唯一要做的就是在你的反序列化代码中为这个成员添加一个默认值,这样已经在数据库中并且没有这个成员的这个类的对象将有一个像样的默认值。
如果您愿意,您还可以对对象格式进行版本控制,它会变得更加复杂。
然而这个方案有一些缺点:
约束很难应用: - 您只能将约束应用于具有列的字段。- 由于某些列仅出现在某些类中,因此数据库需要了解您的类层次结构。
例如,您可能希望将地址放在单独的表中,并添加相关字段(邮政编码、国家、街道、号码等):将所有这些放在主表中会添加太多列。此外,在某些时候,您会想要添加一些客户或其他位于不同表中并且也有地址的东西,因此最好将地址放在单独的表中并引用它们。
对于人或公司等也是如此。
现在一家商店有地址,但购物车没有,我想,所以你必须在数据库 DDL 中表示,如果表中的一行是“shop”类型但不是“cart”类型,则表中的一行必须引用一个地址。
它可能会有点毛茸茸。
此外,例如,如果您有 10 家商店和 100.000 个购物车,出于性能考虑,拆分桌子可能会很有趣,因此您会得到一张漂亮的小快桌和一张大桌子。
现在还有其他解决方案:
例如,您可以将所有代码和基成员放在基类中,但将 tableName 设置为在派生类中更改的类属性。这样,只需更改表名,所有代码都适用于不同的表,但您不必重写任何代码。
然后你每班得到一张桌子。
如果您的类层次结构变得更复杂,您当然可以在每个表上应用上述方法。
两者如何选择?
基本上,如果您制作 Web CMS 并将其存储在表格中,则从 Node 派生的类的对象如下: - 文章 - 带有图例的图像 - 图库 - 等等
所有这些对象基本上都是相同的东西。它们都有一个 Title、一个 TextContent 字段、属于 ParentNode 等
如果您在 TextContent 中对“foo”进行关键字搜索,如果所有对象都在同一个表中,则会容易得多。
如果您想列出 ParentNode 的所有子节点以将它们显示在网页上,那么如果所有内容都在 1 个表中,也会容易得多。
所以在这种情况下,第一种方法确实是一个好处。
现在,在您的情况下,对象并不那么相似。
就个人而言,我什至不会给他们相同的基类。我会创建一个名为“ThingWithCoordinates”的 Mixin(可能更短一些)并将其添加到类中。
现在,也许面包店离商店足够近,它可以从那里继承,但推车和货架,可能不是。
在你的情况下,我肯定会使用几张桌子。而在每个表中,如果需要存储多个类,我会使用第一种方法。
最重要的是,您的类层次结构(以及表格)必须基于相关的东西(汽车经销商和面包店是商店),而不是碰巧存在于实际上没有其他共同点的对象(如购物车和商店)之间存在的共同特征。为此,有一些 mixin 可以共享通用代码,但没有基类。