laravel&mysql连接具有多态关联的表

v8wbuo2f  于 2021-06-19  发布在  Mysql
关注(0)|答案(1)|浏览(364)

更新:下面的模式只是一个需要与其他模块具有多态关系的模块(注解)的简化示例。该应用程序有许多模块(30+)和用户可以通过管理添加新的模块。因此,每个模块都可以“链接”到另一个模块,但是我们在编码时不知道模块名和表名。因此,我们需要一个多态关系。
我正在尝试使用多态关联对动态表名执行连接。
假设以下mysql表

modules table
module_id | name    | table_name
1         | Quote   | quotes
2         | Order   | orders
3         | Product | products

注意:系统允许通过admin添加新模块,因此我们在编码时不知道表名和列名。对于现有模块,模块名或表名也可以随时间而更改。

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行,它将为每行创建一个有说服力的对象。我喜欢雄辩,但在检索大量行时,它的性能远远不够理想。查询生成器更适合这种情况,但不支持多态性。
既然这个关联是在雄辩的层面上完成的,我相信它将需要一个额外的查询。我还没有测试过这个,但是,否则,雄辩者怎么知道要加入哪些表呢?我很高兴在这件事上弄错了。
有时还可能导致其他维护问题,例如更新表名或更改orm类名/命名空间(尽管有解决方案)。
这将绕过外键约束。
我通常不喜欢将表名或模型直接与记录表耦合的想法。这种方法的另一个重要(至少对我来说)缺点是它将数据库模式与应用程序紧密耦合。或者换言之,靠的是雄辩的“魔力”。如果我们在某个时候想要利用node.js、python或golang(我们目前正在实现一个microservices架构),我们可能无法使用它,必须重新构造代码和数据库。
我很少读过像这篇或这篇这样的文章和问题。
我想到的一种方法是使用mysql函数或存储过程动态获取表名并连接结果。我能够使用存储过程和函数动态地获取表名,但似乎不可能连接存储过程的结果。函数似乎不能很好地解决这个问题。
第二种方法是将记录名保存在一个单独的表中。这对获取整个记录(引号、订单等)不起作用,但由于我只需要记录名,所以它工作得很好(当然有适当的索引)。

record_name table
module_id | record_id | name
1         | 23        | Quote #Q-23
2         | 122       | Order #O-122
3         | 55        | Product #P-55

这种方法有一些缺点-第一,它只适用于获取选定的键(在本例中为name)。第二是重复数据和违反其他数据库原则。最后,更新module\u name表需要维护。
因此,我的问题如下—
有没有好的替代方法可以在数据库级别(mysql)或必须在应用程序级别对这种关系进行建模?
mysql存储过程或函数能解决这个问题吗?

ewm0tg9j

ewm0tg9j1#

您的模式是错误的,当您检查 comments.record_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/雄辩的魔力更重要。事实上,更少的魔法更容易和更好的工作。您还应该考虑根本不使用这种数据库抽象,它不会使事情变得更简单,只会带来问题。
另一种可能更好的方法是使用关系表:

- 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

)

相关问题