我试图找出在Hibernate中映射三向@ManyToMany
关系的最佳方法。以下是我的数据模型:
正如您所看到的,TeamPosition表只不过是3个外键。 Hibernate以两个表之间的ManyToMany映射的形式提供有用的功能,并且连接它们的映射表不需要创建第三个Hibernate实体。当然,如果该映射表具有额外的数据,例如“StartDate”,“EndDate”,那么无论如何都需要为映射表创建实体。
是否有可能在其他两个实体的每个实体上创建两个ManyToMany映射,或者如果我创建一个TeamPosition实体并且与OneToMany有关系,那么它会更简单,更少痛苦吗?
我不一定认为答案错误,但有些答案可能比其他答案更正确。
答案 0 :(得分:1)
有趣的问题!
为了清楚起见:数据库的这一点是否记录了某个特定团队在特定赛季所在的联盟组? '联盟组'在这里意味着什么?比如,the premier league vs the championship vs league one?在给定的赛季中,特定联盟组中可以有几支球队吗?
我怀疑让TeamPosition
成为一个实体将是最不痛苦的事情。这些关系都是一对多关系,您可以使用其外键Team
和Season
来构造复合主键,这样就无需为表提供冗余的代理键。通过表连接的查询必须明确命名,但是相当简单。
但是,您也可以将其建模为地图。看起来像:
public class Team {
@ManyToMany
private Map<Season, LeagueGroup> positions;
}
安全性无法保证。我之前只做了一次。如果你从上面生成SQL(在我的例子中使用Hibernate的模式生成器),你得到以下连接表(我给我的实体整数键):
create table Team_LeagueGroup (
Team_id integer not null,
positions_id integer not null,
positions_KEY integer not null,
primary key (Team_id, positions_KEY)
);
使用以下外键使其更清晰:
alter table Team_LeagueGroup
add constraint FKE143A2AEB84635C9
foreign key (Team_id)
references Team;
alter table Team_LeagueGroup
add constraint FKE143A2AEB7412E91
foreign key (positions_id)
references LeagueGroup;
alter table Team_LeagueGroup
add constraint FKE143A2AE8F6AD5C
foreign key (positions_KEY)
references Season;
看起来是正确的。您可以使用通常的注释来自定义表格和列名称。
现在,这避免了为连接表创建实体的需要,但它留下了一些需要的东西。首先,我不知道加入这个的JPQL语法是什么。它将出现在文档中,但您肯定会获得您的侦察徽章,以便探索规范中不起眼的角落以找到它。其次,我不认为有任何方法可以为此设置反向映射。问题在于,虽然球队和赛季的组合唯一地确定了一个联赛组,但对于这三个组中的其他组,情况并非如此。一个特定的球队可能在几个赛季中属于一个特定的联盟组,并且在给定赛季中给定的联盟组将包含几个球队。反向关系需要看起来像class LeagueGroup { Map<Season, Set<Team>> teams; }
,我认为这超出了JPA的力量(虽然我可能是错的)。