【发布时间】:2010-09-26 04:24:26
【问题描述】:
这可能吗?我的意思是,多对多关系的两端可以指向同一张表吗?
【问题讨论】:
标签: hibernate
这可能吗?我的意思是,多对多关系的两端可以指向同一张表吗?
【问题讨论】:
标签: hibernate
如果没有大量可怕的冗余,我不知道你会怎么做。处理两个表之间的多对多关系的标准方法是通过包含两个主键值的第三个表,一个用于第一个表,一个用于第二个表,并带有唯一约束(读取“索引”)所有这些列的组合,并且可能在单独的主键上带有一个或两个重复(非唯一)索引。概述:
CREATE TABLE Table1 (pkcol1 ... PRIMARY KEY, ...);
CREATE TABLE Table2 (pkcol2 ... PRIMARY KEY, ...);
CREATE TABLE MtoM_Table1_Table2
(
pkcol1 ... REFERENCES Table1,
pkcol2 ... REFERENCES Table2,
PRIMARY KEY (pkcol1, pkcol2)
);
-- CREATE INDEX fk1_mtom_table1_table2 ON MtoM_Table1_Table2(pkcol1);
-- CREATE INDEX fk2_mtom_table1_table2 ON MtoM_Table1_Table2(pkcol2);
如果您的 DBMS 是智能的,您可以跳过主键前导列上的单独索引,因为在搜索前导值时也可以使用主键上的索引。
假设 Table1 和 Table2 是同一张表(所以,事实上,我们只有 Table1),如问题所示;这通常仍需要 MtoM_Table1_Table1 映射表 - 与主表不同的表。映射表的 PK(主键)列必须具有单独的名称,但映射表中的两个列(或列集)都将引用 Table1 中的 PK 列。
CREATE TABLE Table1 (pkcol1 ... PRIMARY KEY, ...);
CREATE TABLE MtoM_Table1_Table1
(
pkcol1 ... REFERENCES Table1(pkcol1),
akcol1 ... REFERENCES Table1(pkcol1),
PRIMARY KEY (pkcol1, akcol1)
);
-- CREATE INDEX fk1_mtom_table1_table1 ON MtoM_Table1_Table1(pkcol1);
-- CREATE INDEX fk2_mtom_table1_table1 ON MtoM_Table1_Table1(akcol1);
如果您也想消除映射表,那么您必须在 Table1 中有第二列来保存另一个 PK 值 - 称之为 FKcol1(用于外键列)。这让你有一个困惑:主键是什么?它必须是 PKCol1 和 FKCol1 的组合。但是 FKCol1 应该引用另一行的主键——所以你有一个矛盾。即使假设您设法避免将其作为一个问题(如何,确切地说?),在多对多关系的引用端有“多行”,您必须在主表中有多行具有相同的数据除 FKcol 之外的所有列,但这些列将引用表中的多个(通常不止一个)其他行。这是一个矛盾加上冗余的噩梦,再加上你丢失了简单的主键,再加上弄清楚到底发生了什么是可怕的。
CREATE TABLE Table1
(
pkcol1 ... /* PRIMARY KEY */,
fkcol1 ... /* FOREIGN KEY REFERENCES Table1(pkcol1) */,
...
);
-- CREATE INDEX fk1_table1 ON Table1(pkcol1);
-- CREATE INDEX fk2_table1 ON Table1(fkcol1);
所以,我相信唯一理智的答案是“不 - 你不能在同一个表中表示多对多关系的两端;你必须使用映射表来保留任何工作的机会”像往常一样'在系统中"。
【讨论】:
如果您使用的是 hibernate-annotations,则有一个 @ManyToMany,不确定 XML 等效项。它应该出现在您的发行版的 API 文档中
【讨论】: