java - 在 JPA/Hibernate 中建模二对多关系

标签 java hibernate jpa orm

我有以下实体关系问题。一个“游戏”必须有两个(而且只有两个)“团队”对象。一个“团队”可以有多个“游戏”

据我所知,这是一种二对多关系。但是......我不知道如何在 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仍然可以有方便的方法来设置团队 1 和团队 2 等(业务逻辑强制只有 2 个团队,但是已经完成)但它们映射回 Collection由 Hibernate 使用。

  2. 放弃关系是双向的——选择一个方向(GameTeam 似乎是最合适的)并且只小睡那个关系。寻找 Games一个Team参与 then 成为来自您的 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 的属性side 应该映射为正常的多对一关系;然后使用 mappedByTeam结尾表示 Game “控制”关系。

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

    then 为您的 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 个属性是透明的。

关于java - 在 JPA/Hibernate 中建模二对多关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2177991/

相关文章:

java - Android 在 EditText 中显示来自套接字连接的变量文本

java - 一对多和多对一映射在数据库列中显示为空

java - hibernate 断言失败: null id in entry (don't flush the Session after an exception occurs)

java - 使用 hibernate 将一个对象保存在多个其他对象中

java - Android - Realm 如何通过 boolean 值查询

java - 插件和 jar 中的修订号和构建日期

java - JPA 中的条件 where 子句

java - org.hibernate.TransientObjectException 如果任何多对一字段为空(或未在表单中选择)

java - Oracle 将空字符串转换为 null 但 JPA 不会相应地更新实体缓存

java - 在 Mule 中嵌入 ReSTLet 在 Mule 3.1.2 中无法工作