【问题标题】:Bidirectional OneToMany relationship with composite entity key cause null identifier与复合实体键的双向 OneToMany 关系导致空标识符
【发布时间】:2013-10-25 14:52:53
【问题描述】:

我正在努力使用基于实体的复合主键映射一对多双向关系。我创建了一些代表我想做的类。它们只是制作出来的,因此更容易解释,但我认为它们传达了我正在努力做好的事情。

我没有实现一些接口/方法,但我可以确保当我不将锦标赛集合添加到 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
}

【问题讨论】:

  • 尝试使用@EmbeddedId而不是@IdClass
  • 您能否提供确切的异常消息?当您尝试查找什么类型的实体时出现错误?

标签: java hibernate jakarta-ee jpa


【解决方案1】:

您的问题是您使用不允许类型的@Id 字段(例如PlayerGame 类型)进行注释。详见@Id注解的文档

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

  1. 在您的位置上,我将在您的 Tournament 实体中拥有一个独立的 @Id private Long id; 字段 + 一个带有标准映射的 Game+Player 组合的 @Unique 约束。
  2. 如果你真的想坚持使用@IdClass,你可以尝试在你的锦标赛类中添加两个允许的字段(我发现了一个类似的映射here(搜索@IdClass)。

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

【讨论】:

  • 是的,我意识到使用实体作为 PK 不起作用,所以我更改为 embeddedid 并使用与您编写的相同的映射。但是当我这样做时,我得到了重复的列映射(列和连接列具有相同的名称),所以我不得不添加 insertable=false 和 updateable=false。但是,当我保存时,我没有在数据库中获得记录..
  • 您的意思是您尝试了解决方案 2(@IdClass 而不是 @EmbeddedId)。我已将updatable=false,insertable=false 添加到我的代码中,谢谢。您确定在尝试保存记录时没有遇到异常(很难相信)?如果你得到一个,请发布堆栈跟踪。您如何看待解决方案 1?您是否尝试/考虑过使用@EmbeddedId 而不是@IdClass
  • 我已经改为方法1,我认为通过在可嵌入ID中使用简单字段和另一组manytoone,我更近了一步。我认为这是对的。我明天必须看看。我会发布我发现的内容。
猜你喜欢
  • 1970-01-01
  • 2012-02-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多