1

我为绘图店写了一个应用程序。我的系统中有这些类:商店、购物车、货架和面包店。

它们具有以下属性:

店铺:X、Y、名称、宽度、高度、类型、地址

购物车位置:X、Y、名称、宽度、长度、类型、容量

机架:X、Y、名称、宽度、长度、类型、高度、balance_limit

面包店:X、Y、名称、宽度、长度、类型、open_hours

现在我想在我的数据库中表示这些类。但是你可以看到上面的所有类都有相同的东西,比如:

X、Y、宽度、高度、名称和类型。让它们与众不同的是:

店铺:地址

购物车地点:容量

机架:balance_limit

面包店:open_hours

我知道将来所有这些类型的对象都将拥有自己的新属性,并且它们将获得所有这些对象将同时拥有的新属性。

而且我知道将会有上面没有提到的新类型的对象,它们将具有与商店、购物车位置、货架和面包店相同的一些属性。

我想创建允许我添加新属性和新对象的数据库结构。并添加将同时添加到每个类的新属性。此外,我希望系统设计清晰,并允许我对其进行简单的数据库查询。

所以我的问题是:

我应该为每种类型的对象(商店、购物车位置、货架、面包店)制作一个数据库表,因为它会更清晰,还是应该将它们全部组合到一个表中,因为它们具有相似的属性列表?

我想让你给我一些想法,为什么一种解决方案会比另一种更好。我希望在这里得到一些实用的建议,不仅仅是“你应该这样做,因为这是正确的方式,公理”。

4

6 回答 6

1

这不是一个简单的问题...... 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 可以共享通用代码,但没有基类。

于 2009-08-04T09:06:35.037 回答
1

我的建议:

  1. 正确设计您的域模型,而不考虑数据库问题。共享属性的实体(例如name)并不意味着它们有任何关联。虽然他们很可能...
  2. 将此设计映射到数据库结构,选择众所周知的对象关系结构模式(参见数据库设计)。
  3. 使用适当的 ORM 解决方案开发您的产品(最好是允许您之后修改底层数据库结构的解决方案)。
  4. 如果您遇到性能问题,请考虑(反)规范化您的数据库以解决问题。
于 2009-08-04T09:51:38.833 回答
0

是的,您应该为每个对象使用一个表,因为它们是它们自己的实体。如果将这些表映射到对象,您将无需连接多个表,从而提高效率。

然后每个对象在开发和复杂性方面都是孤立的。

于 2009-08-04T08:47:51.330 回答
0

您从“共享”常见项目的表格中获得什么好处?

如果没有,那么不要这样做 - 只需将它们放在不同的表中(特别是如果它们将来会进一步分歧)。

我猜你没有使用ORM?

于 2009-08-04T08:48:56.633 回答
0

在网上搜索“泛化专业化关系建模”。

当这种模式出现时,您将找到几篇关于如何设计 SQL 数据库的好文章。最好的文章遵循您提供指导而不是制定规范规则的标准。

于 2009-08-04T12:29:19.343 回答
0

如果共性类似于 shop_size ,那么我建议为此创建一个单独的表。

原因是通过标准化您可以获得其他信息,例如,它可以很容易地显示宽度和长度,因为可能有许多商店具有相同的测量值。

稍后,您还可以查看此表中的数据以获取其他信息。

主要是,你得到了灵活性,IMO。

于 2009-08-04T12:38:46.723 回答