与复合实体键的双向OneToMany关系导致空标识符

时间:2013-10-25 14:52:54

标签: java hibernate java-ee jpa

我正在努力将基于entites的复合主键映射一对多双向关系。我创建了一些代表我想做的事情的类。它们刚刚制作,因此更容易解释,但我认为它们传达了我想要做的事情。

我已经省去了实现一些接口/方法,但我可以确保当我没有将一组锦标赛添加到Player / Game实体时它可以工作。所以我的映射出了问题。

当我试图找到一个实体(几乎可以做任何事情)时,Hibernate 4.x会导致一个空标识符错误,而不再说错误。

当我在“one”上有复合主键并且我想要双向导航时,映射这个的正确方法是什么?

@Entity
@IdClass(TournamentPk.class)
public class Tournament {

    @Id
    @ManyToOne
    @JoinColumn("player_id")
    private Player player;  
    @Id
    @ManyToOne
    @JoinColumn("game_id")
    private Game game;
    private int score;

    // Getters and Setters
    // Hashcode and Equals
}

// Primary key class.
public class TournamentPk {

    private Player player;
    private Game game;

    // Getters and Setters
    // Hashcode and Equals
}


@Entity
public class Player {

    // ID
    // Other fields

    @OneToMany(fetchType = FetchType.EAGER, mappedBy = "player")
    private Set<Tournament> tournaments;

    // Getters and Setters
    // Hashcode and Equals
}

@Entity 
public class Game {

    // ID
    // Other fields

    @OneToMany(fetchType = FetchType.EAGER, mappedBy = "game")
    private Set<Tournament> tournaments;

    // Getters and Setters
    // Hashcode and Equals
}

1 个答案:

答案 0 :(得分:2)

您的问题是您使用不允许类型的@Id字段进行了注释(例如类型PlayerGame)。有关详细信息,请参阅@Id注释的文档

注意完整性:some references允许使用@Id注释另一个实体类。

  1. 在您的位置,我的@Id private Long id;实体中会有一个独立的Tournament字段,并且会在游戏+播放器组合中使用标准映射进行@Unique约束。
  2. 如果您真的想坚持使用@IdClass,您可以尝试在锦标赛课程中添加两个允许的字段(我找到了类似的映射here(搜索@IdClass)。

  3.   @Entity
      @IdClass(TournamentPk.class)
      public class Tournament {
    
        @Id
        @Column(name="player_id", insertable = false, updatable = false)
        private Long playerId;
    
        @ManyToOne
        @JoinColumn("player_id")//consider adding cascade=PERSIST
        private Player player;  
    
        @Id
        @Column(name="game_id", insertable = false, updatable = false)
        private Long gameId;
    
        @ManyToOne
        @JoinColumn("game_id")//consider adding cascade=PERSIST
        private Game game;
        private int score;
    
        // Getters and Setters
        // Hashcode and Equals
    }
    
      public class TournamentPk {
    
        private Long playerId;
        private Long gameId;
    
        // Getters and Setters
        // Hashcode and Equals
     }