我有以下实体关系问题。 “游戏”必须有两个(并且只有两个)“团队”对象。 “团队”可以有很多“游戏”
据我所知,这是一种二对多的关系。但是......我不知道如何在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;}
}
但是,正如您所看到的,我不确定如何从注释方面将表链接在一起。有没有人曾经做过这样的事情?任何想法,帮助?
非常感谢!
答案 0 :(得分:6)
我希望有人为此提出一个很棒的解决方案,但这是一个棘手的情况,我从来没有找到一种很好的地图。您的选择包括:
更改关系建模的方式。例如,您可以使用以下内容:
@Entity
public class GameMembership {
Team team;
Game game;
int gamePosition; // If tracking Team 1 vs Team 2 matters to you
}
然后Game
有Collection<GameMembership>
,即您将其建模为多对多。 Game
仍然可以设置方便的方法来设置第1组和第2组等(业务逻辑强制执行只有2个小组,但是已经完成)但是它们会映射回Collection
所使用的冬眠。
放弃让双向关系 - 选择一个方向(Game
→Team
似乎是最合适的)并且只打算关系。找到Games
a Team
然后成为DAO等操作,而不是Team
本身可以访问的内容:
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
结束时“作弊”。 Game
侧的属性应该映射为正常的多对一关系;然后在mappedBy
端使用Team
表示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个属性是透明的。
答案 1 :(得分:2)
如果您的游戏拥有第一个玩家 - 一个团队(从团队列表中选择)和第二个玩家 - 一台计算机(从计算机列表中选择),将会发生什么:
如果您现在将“计算机”替换为另一个“团队”的玩家,您将获得两个外键进入团队表。
我的JPA有点生疏,但我相信您使用@OneToOne
注释建模外键关系,如下所示:
@OneToOne(cascade = {CascadeType.ALL}, optional = false)
@JoinColumn(name = "team1")
和第二个:
@OneToOne(cascade = {CascadeType.ALL}, optional = false)
@JoinColumn(name = "team2")
答案 2 :(得分:2)
你有一个@OneToMany关系(我想Game与团队有@ManyToOne关系),我的建议是:
使用封装来实现目标
@Entity
public class Team {
private Game game1;
private Game game2;
private List<Game> gameList = new ArrayList<Game>();
public void setGame1(Game game1) {
// You can use index 0 to store your game1
if(getGameList().size == 0)
getGameList().add(game1);
else
getGameList().set(0, game1);
}
@Transient
public Game getGame1() {
if(getGameList().size() == 0)
return null;
return getGameList().get(0);
}
public void setGame2(Game game2) {
// You can use index 1 to store your game2
switch(getGameList().size()) {
case 0:
getGameList().add(null);
getGameList().add(game2);
break;
case 1:
getGameList().add(game2);
break;
case 2:
getGameList().set(1, game2);
break;
}
}
@Transient
public Game getGame2() {
if(getGameList().size() < 2)
return null;
return getGameList().get(1);
}
@OneToMany
@JoinColumn(name="TEAM_ID")
public List<Game> getGameList() {
return this.gameList;
}
}
请注意,有时你必须亲自做你的工作。所以封装可能是你问题的关键。
的问候,
答案 3 :(得分:1)
我认为你有两个一对多关系,而不是一个两对多关系。
答案 4 :(得分:0)
这会有效吗?
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>Private Page</h1>
</body>
</html>