我有以下实体关系问题. “游戏”必须有两个(只有两个)“团队”对象. “团队”可以有很多“游戏”
据我所见,这是一种两对多的关系.但是,我不知道如何在JPA中建模.例如,我要做这样的事情
@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;} }
但是,如您所见,我不知道如何从注释方面将表连接在一起.有没有人曾经做过这样的事情?任何想法,帮助?
非常感谢!
解决方法
我希望有人想出一个很棒的解决方案,但这是一个棘手的情况,我从来没有找到一种方法映射得很好.您的选择包括:
>改变你建立关系的方式.例如,你可以这样做:
@Entity public class GameMembership { Team team; Game game; int gamePosition; // If tracking Team 1 vs Team 2 matters to you }
然后游戏有一个集合< GameMembership>,即您将它建模为多对多.游戏仍然可以有方便的方法来设置Team 1和Team 2等(业务逻辑强制只有2个团队,但是已经完成),但是他们映射回到Hibernate使用的集合.
放弃关系是双向的 – 选择一个方向(游戏→团队似乎最合适),只打动这种关系.查找一个团队参与的游戏随后成为您的DAO等操作,而不是团队本身可以访问的操作:
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(); } }
或类似的东西…
>沿着你所在的路线继续进行,但是在队结束时要“欺骗”.游戏端的属性应该映射为正常的多对一关系;然后在Team端使用mappedBy来表示Game的控制关系.
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); // Or use google-collections Sets.union() for bonus points return allGames; }
所以你的班级的呼叫者,它是透明的,有2个属性.