[英]Modelling a Two to Many Relationship in JPA/Hibernate
我有以下實體關系問題。 “游戲”必須有兩個(並且只有兩個)“團隊”對象。 一個“團隊”可以有很多“游戲”
據我所知,這是一種二對多的關系。 但是......我不知道如何在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 }
然后Game
有一個Collection<GameMembership>
,即你將它建模為多對多。 Game
仍然可以有方便的方法來設置Team 1和Team 2等(業務邏輯強制只有2個團隊,但是已經完成)但是它們映射回Hibernate使用的Collection
。
放棄讓雙向關系 - 選擇一個方向( Game
→ Team
似乎是最合適的)並且只打算那種關系。 找到一個Team
參與的Games
然后成為你的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
方面的屬性應該映射為正常的多對一關系; 然后在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個屬性是透明的。
考慮如果您的游戲擁有第一個玩家 - 一個團隊(從團隊列表中選擇)和第二個玩家 - 一台計算機(從計算機列表中選擇)會發生什么:
如果您現在將“計算機”替換為另一個“團隊”的玩家,您將獲得兩個外鍵進入團隊表。
我的JPA有點生疏,但我相信你用@OneToOne
注釋建模外鍵關系,如下所示:
@OneToOne(cascade = {CascadeType.ALL}, optional = false)
@JoinColumn(name = "team1")
第二個用:
@OneToOne(cascade = {CascadeType.ALL}, optional = false)
@JoinColumn(name = "team2")
你有一個@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;
}
}
請注意,有時您必須手工完成工作。 所以封裝可能是你問題的關鍵。
問候,
我認為你有兩個一對多的關系,而不是一對二關系。
這會工作:
@OneToMany
@JoinFormula(value = "SELECT g.id FROM game g WHERE g.homeTeam = id or g.awayTeam=id")
private Set<Game> games;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.