在JPA / Hibernate中建模两对多关系 [英] Modelling a Two to Many Relationship in JPA/Hibernate
问题描述
我有以下实体关系问题。一个游戏必须有两个(并且只有两个)团队对象。一个团队可以有很多游戏
就我所见,这是一个两对多的关系。但是......我不知道如何在JPA中对此进行建模。例如,我打算做这样的事情......
@Entity
public class Team extends BaseObject {
私人长ID;
私人设置<游戏>游戏;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId(){return id;}
public void setId(Long id){this .id = id;}
@OneToMany(mappedBy =game)
public Set< Game> getGames(){返回游戏;}
public void setGames(Set< Game> games){this.games = games;}
}
@Entity
public类游戏扩展BaseObject {
private Long id;
私人团队team1;
私人团队team2;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId(){return id;}
public void setId(Long id){this .id = id;}
@这是问题 - 我使用何种注释?
public Team getTeam1(){return team1;}
public void setTeam1(Team team1){this.team1 = team1;}
@这是问题 - 注释的含义我用?
public Team getTeam2(){return team2;}
public void setTeam2(Team team1){this.team2 = team2;}
}
但是,正如您所看到的,我不确定如何从注释端将表连接在一起。有没有人曾经做过这样的事情?任何想法,帮助?
非常感谢!
会喜欢有人提出一个真棒解决方案,但这是一个棘手的情况,我从来没有能够找到一个很好的映射方式。您的选择包括:
-
改变您对关系建模的方式。例如,你可能有这样的东西:
@Entity
公共类GameMembership {
团队团队;
游戏游戏;
int gamePosition; //如果跟踪Team 1 vs Team 2对你很重要
$ / code>然后
Game
有一个集合< GameMembership>
,即你将它建模为多对多。游戏
仍然可以用于设置Team 1和Team 2等方便的方法(业务逻辑强制只有2个团队,但是这样做),但他们映射回Hibernate使用Collection
。 -
放弃关系是双向的 - 选择一个方向(
游戏
→团队
似乎是最合适的)并且只打那个关系。查找游戏
a团队
参与进来,然后成为您的DAO等的操作,而不是可从团队
本身:
公共类GameDAO {
.. ..
public Collection< Game> gamesForTeam(Team t){
....
Query q = session.createQuery(FROM Game WHERE team1 =:team OR team2 =:team);
q.setParameter(team,t);
return q.list();
}
}
或类似的东西...
-
继续沿着您所采用的路线行驶,但在
Team
结尾处欺骗。在Game
一侧的属性应该被映射为正常的多对一关系;然后在团队
末端使用mappedBy
来指示游戏
'控制'关系。public class Team {
...
@OneToMany(mappedBy = team1)
private Set< Game> team1Games;
@OneToMany(mappedBy =team2)
private Set< Game> team2Games;
和然后为您的API提供了一个便利的属性(
team1Games
和team2Games
仅供Hibernate使用):
@Transient
public Set< Game> getGames(){
Set< Game> allGames = new HashSet< Game>(team1Games);
allGames.addAll(team2Games);
//或者使用google-collections Sets.union()获得奖励积分
返回allGames;
}
所以对于你的类的调用者来说,它有两个属性是透明的。 / p>
I have the following entity relationship problem. A "Game" must have two (and only two) "Team" objects. A "Team" can have many "Games"
This, as far as I can see is a Two-to-Many relationship. However...I don't know how to model this in JPA. Eg, I was going to do something like this...
@Entity
public class Team extends BaseObject {
private Long id;
private Set<Game> games;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {return id;}
public void setId(Long id) {this.id = id;}
@OneToMany(mappedBy = "game")
public Set<Game> getGames() {return games;}
public void setGames(Set<Game> games) {this.games = games;}
}
@Entity
public class Game extends BaseObject {
private Long id;
private Team team1;
private Team team2;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {return id;}
public void setId(Long id) {this.id = id;}
@ HERE IS THE PROBLEM - WHAT ANNOTATION DO I USE?
public Team getTeam1() {return team1;}
public void setTeam1(Team team1) {this.team1 = team1;}
@ HERE IS THE PROBLEM - WHAT ANNOTATION DO I USE?
public Team getTeam2() {return team2;}
public void setTeam2(Team team1) {this.team2 = team2;}
}
But, as you can see, I'm not sure how to link the tables together from an annotation side. Has anyone ever done something like this before? Any ideas, help?
thanks very much!
I would love for someone to come up with an awesome solution to this, but it's a tricky situation which I've never been able to find a way to map very well. Your options include:
Change the way you model the relationship. For example, you could have something like:
@Entity public class GameMembership { Team team; Game game; int gamePosition; // If tracking Team 1 vs Team 2 matters to you }
and then
Game
has aCollection<GameMembership>
, i.e. you model it as many-to-many.Game
can still have convenient methods for setting Team 1 and Team 2, etc, (business logic to enforce that there are only 2 Teams, however that's done) but they map back onto theCollection
as used by Hibernate.Give up on having the relationship be bidirectional -- pick one direction (
Game
→Team
seems the most appropriate) and nap only that relationship. Finding theGames
aTeam
is involved in then becomes an operation from your DAO etc, rather than something that's accessible from theTeam
itself:public class GameDAO { .... public Collection<Game> gamesForTeam(Team t) { .... Query q = session.createQuery("FROM Game WHERE team1 = :team OR team2 = :team"); q.setParameter("team", t); return q.list(); } }
or something similar...
Continue along the route you're taking, but 'cheat' at the
Team
end. The properties at theGame
side should be mapped as normal many-to-one relationships; then usedmappedBy
at theTeam
end to indicate thatGame
'controls` the relationship.public class Team { ... @OneToMany(mappedBy="team1") private Set<Game> team1Games; @OneToMany(mappedBy="team2") private Set<Game> team2Games;
and then have a convenience property for your API (
team1Games
andteam2Games
are just for Hibernate's use):@Transient public Set<Game> getGames() { Set<Game> allGames = new HashSet<Game>(team1Games); allGames.addAll(team2Games); // Or use google-collections Sets.union() for bonus points return allGames; }
so to callers of your class, it's transparent that there are 2 properties.
这篇关于在JPA / Hibernate中建模两对多关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!