如何在hibernate中表示与同一个表/实体的多对多关系?

时间:2008-12-10 03:49:02

标签: hibernate

这可能吗?我的意思是,多对多关系的两端是否都指向同一个表?

2 个答案:

答案 0 :(得分:1)

如果没有巨大而可怕的冗余,我不确定你会怎么做。处理两个表之间多对多关系的标准方法是通过第三个表,该表包含两个主键值,一个用于第一个表,一个用于第二个表,具有唯一约束(读取“索引”)所有这些列的组合,并且可能在单独的主键上有一个或两个重复(非唯一)索引。概括地说:

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(主键)列的单独名称,但映射表中的两列(或列集)将引用表1中的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);

所以,我确信唯一合理的答案是“不 - 你不能代表同一个表中多对多关系的两端;你必须使用映射表来保留很多工作机会”像往常一样'在系统中“。

答案 1 :(得分:0)

如果您正在使用hibernate-annotations,那么有一个@ManyToMany,不确定XML等价物。它应该出现在您的发行版的API文档中