单表继承

4

在我的数据库设计问题中的一个答案中,建议使用单表继承。我已经搜索了一些相关信息,但似乎找不到很清晰的解释。

基本上,我所理解的是,您需要创建一个大表,其中包含所有字段和一个类型字段,然后您的ORM层使用类型字段为您提供不同的对象视图。这样理解对吗?

更重要的是,单表继承是否是“认可”的数据库设计技术?我的意思是说,使用它是否“合理”?同时,使用它是否安全,还是会导致问题?

另一个问题是,这在Rails中的运行情况如何?我在Rails中找到了一些参考资料,但是通过非传统方式进行操作是否会导致问题?

非常感谢任何帮助。

7个回答

5
这是个好主意吗?这要看情况而定。使用这种方法会破坏规范化,因为一个表不只有一个目的。当你第n次扩展基类时会发生什么?你必须向表中添加列。大多数现代数据库对此没有问题,因为你可以修改表,但是如果进行重构并删除一个类,那怎么办呢?现在你有了没有用途的列。
一个经验法则-如果大部分设计已经完成,那么使用这种方法可能是安全的。如果设计经常更改-你有其他问题,需要锁定用例/用户需求。(是的,不太符合XP友好)
我不知道Rails的影响。

2

STI(Single Table Inheritance)是一种处理面向对象和面向数据库思维不匹配的方式。它允许在数据库中合理地表示信息,并在对象模型中使用不同的表示。

例如,我有一个应用程序,每个产品都包含一个或多个费用,每个费用的计算方式略有不同。在我的对象模型中,我想要拥有Fee类的子类,每个子类都知道如何计算自己。然而,我并不想为每种费用类型创建一个表,因此我将Fee作为基类,fees作为表,其中包含所有子类型所需的字段的联合,以及一个“type”列,其值对应于相关子类的名称。ActiveRecord会处理其余的操作。


我认为另一种设计可能会更加灵活和可扩展。在模型中添加一个<fees>类型(一组)方法(或者如果这些方法也用于其他地方,则使用模块mixin)来有条件地计算费用结构,取决于:type。这将使其更具可扩展性。
  1. 您可以拥有任意数量的不同“类型”。
  2. 您可以随时扩展逻辑而不必担心数据库结构。
  3. 数据更规范化。
有什么缺点吗?(也许我的想法被好处所迷惑了,我看到了什么)
- Ram on Rails React Native
@ramonrails - 我并不完全不同意,尽管我会说,如果我理解你的方法并记得我的方法,那么这两种方法实际上是相同的,只不过我的方法是应用了重构的产物,这取决于上下文是否适当。看看优点:1.类似于类,当然,我不必触及任何现有模块?2.同上,虽然如果出现完全新的东西,模式必须更改;3.在那个方面我可能漏掉了什么 :-) - Mike Woodhouse

1
简而言之,单表继承(STI)是一种设计模式,允许将面向对象编程的继承关系映射到数据库中。如果您从ActiveRecord模型对象定义任何子类,则应考虑使用STI。
STI最初在Martin Fowler的《企业应用架构模式》一书中有记录,并且也在DHH的经典Rails书籍《敏捷Web开发与Rails》(第18.4节,我想)中有描述。我建议您参考这些书籍,因为它们提供了比我在此处能够做到的更好的解释。
我强烈反对www.matthewpaulmoore.com(由本帖中的robintw链接)所表达的观点,即STI本质上是一件坏事。这似乎是一种有些天真的看法,忽略了面向对象编程继承的使用。我已经在Rails中使用STI创建了一些优雅的解决方案,但我想你可以滥用任何设计模式。

0

权威的参考资料。它允许单个表存储具有共同基类的多个对象。

Ruby on Rails使用一个名为Active Record的库。这是一个常见的Ruby框架,支持STI。


0

我只能从(新的)ADO实体框架角度来谈论,这包括了表对类型(TPT)功能。

这里是一系列介绍核心概念(使用实体框架)的好博客文章,还有一个MSDN文件 这里

使用nHibernate进行TPT时也似乎有一些指导资料,在这里可以找到。

这个链接解释了SQL Server中的表对类型继承。这似乎有对概念的很好总结和介绍。

我不确定它对Rails会产生什么影响。


0

我一段时间前阅读了那篇文章,当时就把它撇到一边了 - 作者只是笼统地断言他从来没有见过 STI 的好用处,因此没有人应该使用它,而从未解释他实际在谈论什么。为什么它不是一个好的使用方式?他见过哪些情况?等等。 - Orion Edwards

0

一般来说,我觉得它很有用,但是我遇到了一些bug

链接中的示例可能会提供一个有用的图片,展示你如何使用它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接