Hibernate:配置三向多对多关系的最佳方法 [英] Hibernate: Best way to configure 3-way many to many relationship

查看:102
本文介绍了Hibernate:配置三向多对多关系的最佳方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试找出在Hibernate中映射三向@ManyToMany关系的最佳方法.以下是我的数据模型:

您可以看到TeamPosition表只不过是3个外键. Hibernate通过两个表之间的ManyToMany映射以及将它们联接在一起的映射表的形式提供了有用的功能,而无需创建第三个Hibernate实体.当然,如果该映射表具有其他数据,例如"StartDate","EndDate",则无论如何都需要为该映射表创建实体.

是否可以在每个实体上为其他两个实体创建两个ManyToMany映射,或者如果我创建一个TeamPosition实体并与其具有OneToMany关系,是否会更简单,更轻松?

我不一定认为答案有误,但是某些答案可能比其他答案更正确.

解决方案

有趣的问题!

为清楚起见:数据库的这一部分记录的是特定球队在特定季节所在的联赛组吗? 同盟群体"在这里是什么意思?例如,英超联赛联盟一个?在给定的季节中,一个给定的联赛组中可以有几支球队?

我怀疑使TeamPosition成为实体将是最痛苦的事情.这些关系都是一对多的,您可以将其外键用于TeamSeason来构造复合主键,这将避免为表提供冗余代理键.通过表进行联接的查询将必须对其进行显式命名,但是非常简单.

但是,您也可以将其建模为地图.看起来像这样:

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的功能(尽管我可能是错的).

I am trying to figure out the best way to map a three way @ManyToMany relationship in Hibernate. The following is my data model:

As you can see the TeamPosition table is nothing more than 3 foreign keys. Hibernate provides helpful functionality in the form of a ManyToMany mapping between two tables and a mapping table that joins them where a third Hibernate entity does not need to be created. Of course if that mapping table had additional data like "StartDate', 'EndDate' for example then the entity will need to be created for the mapping table anyway.

Is it possible to create two ManyToMany mappings on each entity for the other two entities or would it just be simpler and less painful if I create a TeamPosition entity and have OneToMany relationships to this instead?

I don't necessarily think there is a wrong answer, but some answers might be more correct than others.

解决方案

Interesting problem!

For clarity: is this bit of the database recording the league group a particular team was in in a particular season? What does 'league group' mean here? Like, the premier league vs the championship vs league one? Can there be several teams in a given league group in a given season?

I suspect that making TeamPosition an entity will be the least painful thing to do. The relationships are all one-to-many, and you can use its foreign keys to Team and Season to construct a composite primary key, which will avoid the need to give the table a redundant surrogate key. Queries which join through the table will have to name it explicitly, but will be fairly straightforward.

However, you could also have a go at modelling this as a map. Something that looks like:

public class Team {
    @ManyToMany
    private Map<Season, LeagueGroup> positions;
}

Safety not guaranteed. I have only done this once before. If you generate SQL from the above (using Hibernate's schema generator in my case), you get the following join table (i gave my entities integer keys):

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)
);

With the following foreign keys making this a bit clearer:

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;

Which looks about right. You can use the usual annotations to customise the table and columns names as you see fit.

Now, that avoids the need to create an entity for the join table, but it leaves a few things to be desired. Firstly, i have no idea what the JPQL syntax for joining across this is. It'll be in the documentation, but you'll definitely get your scout badge for exploring obscure corners of the spec for finding it out. Secondly, i don't think there's any way to set up a reverse mapping for this. The problem is that although the combination of a team and a season uniquely identifies a league group, that isn't true for the other pairs of those three. A given team may be in a given league group over several seasons, and a given league group in a given season will contain several teams. The reverse relationships would need to look something like class LeagueGroup { Map<Season, Set<Team>> teams; }, and i think that's beyond the power of JPA (although i could be wrong).

这篇关于Hibernate:配置三向多对多关系的最佳方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆