问题
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