一尘不染

在JPA / Hibernate中建立一对多关系模型

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;}
}

但是,正如您所看到的,我不确定如何从注释侧将表链接在一起。有人曾经做过这样的事情吗?有什么想法吗?

非常感谢!


阅读 275

收藏
2020-06-20

共1个答案

一尘不染

我希望有人能提出一个很棒的解决方案,但是这是一个棘手的情况,我从未能找到一种很好的映射方法。您的选择包括:

  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仍然可以使用方便的方法来设置团队1和团队2,等等(业务逻辑来强制只有2个团队,但是已经完成了),但是它们映射回Collection了Hibernate所使用的。

  1. 放弃建立双向关系-选择一个方向(GameTeam似乎最合适),然后仅打na该关系。找到所涉及的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();
    }
    

    }

或类似的东西

  1. 继续沿您所走的路线行驶,但最后会“作弊” TeamGame侧面的属性应映射为正常的多对一关系;然后mappedByTeam末尾用来表示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个属性是透明的。

2020-06-20