【问题标题】:Modelling a product catalog model in Grails在 Grails 中为产品目录模型建模
【发布时间】:2010-12-06 16:40:02
【问题描述】:

我正在调查一个个人 Grails 项目,并希望组合一个域模型来表示产品目录。我真的无法决定最好的方法。我将有许多不同的产品类别,尽管许多类别将只有一组在所有类别之间共享的基本属性(例如产品名称、产品描述、价格等)。但是,某些产品将具有特定于其类别的其他属性。

我研究了实体属性值 (EAV) 模型技术,该技术提供了一种非常可扩展的解决方案。而且,我考虑了使用显式 OO 继承模型的路线,其中我有基础 Product 类的子类来表示具有附加属性的任何产品。

显然,第二种方法的可扩展性较差 - 添加新产品类别需要一个新实体,并且可能需要一个用于前端的自定义视图/编辑器。然而,作为一名开发人员,我认为编程模型明显更清晰,更适合编写代码。

EAV 方法将允许动态可扩展性,但会导致更神秘的编程模型,并且会在数据库中产生性能开销(复杂的表连接)。前端的视图/编辑器可以动态生成,以包含产品类别的任意数量的自定义属性——尽管我确信从可用性的角度来看,这种动态生成还不够的情况会出现。

当我考虑像 Grails 这样的框架时,沿着创建显式继承模型的路线走下去似乎是有意义的。我不相信像 Grails 这样的框架会非常适合 EAV 方法 - Grails 的许多好处会在复杂性中丢失。但是,我不确定这种方法是否会随着产品类别数量的增加而实际扩展。

我真的很想听听其他人在此类建模挑战中的经验!

【问题讨论】:

    标签: database database-design grails data-modeling


    【解决方案1】:

    我遇到过类似的情况,就选择了继承解决方案。进入这个我知道我的课程永远不会超过 10 个,所以我并不担心复杂性的指数级增长。尽管每个类都需要视图和控制器,但您可以采取一些措施来减少代码重复。首先要做的是将所有常见的视图代码放在模板中。例如,如果您的所有类都有价格、名称和描述,则应将允许显示和编辑的视图代码放入模板中。您可以简单地做一个

    ,而不是在每个视图中都有重复的代码行
    <g:render template=”/baseView</g>render>
    

    有关模板的更多信息,请参阅http://www.grails.org/Tag+-+render 我发现有用的第二件事是将所有共享控制器代码移动到一个类中并定义我可以从我的实际控制器调用的闭包。这变得非常难看,因为我的保存方法不仅可以确保基类的字段得到正确处理,而且还可以为继承类的极端情况编写代码。回顾这一点,一个更好的选择可能是将自定义行为定义为需要它或使用服务的域类的函数。话虽如此,将代码放入可以从控制器调用的闭包中仍然很有帮助,因为它可以让我拥有一行长的控制器主体,而不是 30 或 40 个。如果我必须修改处理基类的代码,我可以编辑它在哪里定义了闭包,并且该更改将反映在我的所有控制器中,而无需对控制器的实际源文件进行任何代码更改。这非常有用,让我可以在一个地方编辑代码,而不是跨 10 个控制器编辑重复的代码。

    【讨论】:

    • 谢谢,这里有一些非常有用的想法。我确实觉得继承路线感觉更舒服。就像您的情况一样,我认为实体的数量不会达到成为问题的程度。
    • 一个问题...如果我想要一个资源路径来查找产品,例如/products/{productId},我怎么知道要查找哪个产品实体,以及相应地要呈现哪个视图?很想知道你现在是如何解决这个问题的。
    • 我不必对我的程序执行此操作。我假设您可以使用通用产品控制器,对类类型进行 BaseClass.get(id) 测试,然后重定向到正确的控制器。
    • 酷,我在考虑这些思路,但更愿意避免额外的查询 - 但是,这几乎不是主要开销。
    【解决方案2】:

    Inheritance 在 Hibernate 和 GORM 上运行良好。考虑 using table-per-subclass 映射,因为您不能使用(默认)table-per-hierarchy 继承映射定义 NOT NULL 约束。

    您也可以将composition 用于“不那么”常见但共享的属性。

    EAV 的“标准”是,是否需要在不改变数据模型的情况下引入新属性?

    实际上,像您这样的应用程序使用继承和 EAV 的组合。

    您在查询JOINed 表时担心性能问题。如果您index SQL WHERE 语句中包含的列,这通常不是问题。
    (GORM/Hibernate 将自动创建外键,这也很重要。)(鉴于必要的索引已经到位,并且 DBMS 提供了一个不错的查询优化器(即 PostgreSQL 或 SQL Server - 也许不是 MySQL),你可以在 50 毫秒或更短的时间内使用 10 个连接从数百万条记录中进行选择。)

    最后,关于您的问题,最近有一个出色的 discussion

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-27
      • 2019-04-05
      • 2011-01-03
      • 2012-07-19
      • 2021-05-04
      • 1970-01-01
      相关资源
      最近更新 更多