拉维公司;MySQL连接具有多态关联的表

拉维公司;MySQL连接具有多态关联的表,mysql,laravel,polymorphic-associations,Mysql,Laravel,Polymorphic Associations,更新: 下面的模式只是一个模块(注释)的简化示例,该模块需要与其他模块具有多态关系。该应用程序有许多模块(30+),用户可以通过admin添加新模块。因此,每个模块都可以“链接”到另一个模块,但我们在编码时不知道模块名和表名。因此,我们需要一个多态关系 我正在尝试使用多态关联使用动态表名执行联接 假设以下MySQL表 modules table module_id | name | table_name 1 | Quote | quotes 2 | Or

更新: 下面的模式只是一个模块(注释)的简化示例,该模块需要与其他模块具有多态关系。该应用程序有许多模块(30+),用户可以通过admin添加新模块。因此,每个模块都可以“链接”到另一个模块,但我们在编码时不知道模块名和表名。因此,我们需要一个多态关系

我正在尝试使用多态关联使用动态表名执行联接

假设以下MySQL表

modules table
module_id | name    | table_name
1         | Quote   | quotes
2         | Order   | orders
3         | Product | products
注意:系统允许通过管理员添加新模块,因此我们在编码时不知道表名和列名。现有模块的模块名或表名也可以随时间而更改

quotes table
id | name
22 | "Quote #Q-22"
23 | "Quote #Q-23"

orders table
id  | name
122 | "Order #O-122"
123 | "Order #O-123"

products table
id  | name
55 | "Product #P-55"
56 | "Product #P-56"

comments table
id | module_id | record_id | text
1  | 1         | 23        | hello
2  | 2         | 122       | big
3  | 3         | 55        | world
我想运行一个将返回以下行的查询:

comments
id | name          | text
1  | Quote #Q-23   | hello
2  | Order #O-122  | big
3  | Product #P-55 | world
Laravel允许将ORM类名或表名直接存储在父表上

这就让ORM来处理这种关系,据我所知,通常会带来一些性能代价。 我认为性能会受到显著影响的原因是:

  • 雄辩的开销。对于1000行,它将为每一行创建一个有说服力的对象。我喜欢雄辩,但在检索大量行时,它的性能远远不够理想。查询生成器更适合这种情况,但不支持多态性
  • 由于关联是在雄辩的层次上进行的,我相信它将需要额外的查询。我还没有测试过这一点,但是,否则,Eloquent怎么知道要加入哪些表呢?我很乐意在这一点上出错
  • 它有时还可能导致其他维护问题,例如更新表名或更改ORM类名/命名空间(尽管有解决方案)
  • 这将绕过外键约束 我通常不喜欢将表名或模型直接与记录表耦合的想法。 这种方法的另一个重要缺点(至少对我来说)是它将数据库模式与应用程序紧密耦合。或者换句话说,依赖于雄辩的“魔力”。如果我们在某个时候想要利用Node.js、Python或GoLang(我们目前正在实现一个microservices架构),我们可能无法使用它,必须重新构造代码和数据库

    我很少读其他的文章和问题,比如,或者

    我想到的一种方法是使用MySQL函数或存储过程动态获取表名并连接结果。我能够使用存储过程和函数动态获取表名,但似乎不可能连接存储过程的结果。函数似乎也不能解决这个问题

    第二种方法是将记录名保存在一个单独的表中。这不适用于获取整个记录(引号、订单等),但因为我只需要记录名,所以它可以正常工作(当然,有适当的索引)

    这种方法有几个缺点-第一,它只适用于获取选定的关键点(本例中的名称)。第二,它复制数据,违反其他数据库原则。最后,更新模块名称表需要维护

    因此,我的问题如下:

  • 是否有好的替代方法在数据库级别(MySQL)建模这种关系,或者必须在应用程序级别建模
  • MySQL存储过程或函数可以解决这个问题吗

  • 您的模式错误,当您检查
    注释的外键约束时,您会注意到。记录\u id

    修复外键约束后,输出应如下所示:

    comments table
    id | quotes_id | orders_id | products_id | text
    1  | 22        | null      | null        | Text comment
    2  | null      | 122       | null        | Text comment
    3  | null      | null      | 55          | Text comment
    
    正确的数据库模式(关系)比Laravel/Elount magic更重要。事实上,更少的魔法更容易和更好的合作。 你也应该考虑不使用这种数据库抽象,它不会使事情变得更简单,而只是引入问题。 另一种可能更好的方法是使用关系表:

    - comments table
    id | text
    1  | hello
    2  | world
    
    - quote_has_comment table
    quote_id | comment_id
    22       | 1
    (with constraint quote_id+comment_id beeing unique
    

    )

    谢谢你的回答,但我不确定它是否真的解决了问题。在我们的解决方案中,可以有许多模块,用户可以创建新模块。因此,您建议的第一种方法不起作用,因为我需要提前知道要加入哪些表。问题是我们只在运行时知道它。当然,我们可以在创建新模块时自动创建新表、索引和添加列。似乎第二种方法也依赖于一个已知的数据库模式。我给出的带有注释的示例只是一个,但它可以是许多其他关系,例如附加到一些记录(如Customer、Order)的支持通知单,并且还包含注释。有时支持票证会附加到报价,有时附加到订单,有时附加到产品或任何可添加的自定义模块。因此,每个模块都可以连接到另一个模块,甚至不止一次。如果您在运行时只知道您有哪些关系,那么您在其他地方就犯了很大的错误。您可以轻松地编写代码,以便在运行前了解所有关系。如果你像你开始的那样继续下去,你会用很多魔法建造一些非常糟糕的东西。
    - comments table
    id | text
    1  | hello
    2  | world
    
    - quote_has_comment table
    quote_id | comment_id
    22       | 1
    (with constraint quote_id+comment_id beeing unique