Hibernate: Best way to configure 3-way many to many relationship

為{幸葍}努か 提交于 2019-12-24 05:27:06

问题


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.


回答1:


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



来源:https://stackoverflow.com/questions/11638412/hibernate-best-way-to-configure-3-way-many-to-many-relationship

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!