簡體   English   中英

在JPA / Hibernate中建模兩對多關系

[英]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;}
}

但是,正如您所看到的,我不確定如何從注釋端將表鏈接在一起。 有沒有人曾經做過這樣的事情? 任何想法,幫助?

非常感謝!

我希望有人能夠提出一個很棒的解決方案,但這是一個棘手的情況,我從來沒有找到一種很好的地圖。 您的選擇包括:

  1. 改變你建立關系的方式。 例如,你可以有類似的東西:

     @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

  2. 放棄讓雙向關系 - 選擇一個方向( GameTeam似乎是最合適的)並且只打算那種關系。 找到一個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(); } } 

    或類似的東西......

  3. 繼續沿着你正在走的路線,但在Team結束時“欺騙”。 Game方面的屬性應該映射為正常的多對一關系; 然后在Team端使用mappedBy來表示Game '控制'這種關系。

     public class Team { ... @OneToMany(mappedBy="team1") private Set<Game> team1Games; @OneToMany(mappedBy="team2") private Set<Game> team2Games; 

    然后為你的API提供便利屬性( team1Gamesteam2Games僅供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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM