在JPA/Hibernate中建模两对多关系

Bri*_*ian 10 java orm hibernate jpa

我有以下实体关系问题."游戏"必须有两个(并且只有两个)"团队"对象.一个"团队"可以有很多"游戏"

据我所知,这是一种二对多的关系.但是......我不知道如何在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;}
}
Run Code Online (Sandbox Code Playgroud)

但是,正如您所看到的,我不确定如何从注释端将表链接在一起.有没有人曾经做过这样的事情?任何想法,帮助?

非常感谢!

Cow*_*wan 6

我希望有人能够提出一个很棒的解决方案,但这是一个棘手的情况,我从来没有找到一种很好的地图.您的选择包括:

  1. 改变你建立关系的方式.例如,你可以有类似的东西:

    @Entity
    public class GameMembership {
       Team team;
       Game game;
       int gamePosition; // If tracking Team 1 vs Team 2 matters to you
    }
    
    Run Code Online (Sandbox Code Playgroud)

    然后Game有一个Collection<GameMembership>,即你把它建模为多对多.Game仍然可以有方便的方法来设置Team 1和Team 2等(业务逻辑强制只有2个团队,但是已经完成),但是它们映射回CollectionHibernate所使用的.

  2. 放弃让双向关系 - 选择一个方向(GameTeam似乎是最合适的)并且只打盹.找到Gamesa 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();
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    或类似的东西......

  3. 继续沿着你正在走的路线,但最后"欺骗" Team.Game侧面的属性应该映射为正常的多对一关系; 然后mappedByTeam末尾用来表示Game'控制'这种关系.

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

    有一个简便属性为您的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;
        }
    
    Run Code Online (Sandbox Code Playgroud)

    所以对于你班级的来电者来说,有2个属性是透明的.