【问题标题】:Hibernate foreign key with a part of composite primary key使用复合主键的一部分休眠外键
【发布时间】:2015-12-14 00:46:39
【问题描述】:


我必须使用 Hibernate,但我不太确定如何解决这个问题,我有 2 个具有 1..n 关系的表,如下所示:

-------- 表_A -------- col_b (pk) col_c (pk) [其他领域] -------- 表_B -------- col_a (pk) col_b (pk) (fk TABLE_A.col_b) col_c (fk TABLE_A.col_c) [其他领域]

我如何使用 Hibernate 来管理这个?

我不知道如何声明包含主键一部分的外键。

我的数据库架构是从 Hibernate 模型生成的。

【问题讨论】:

  • 如果你想和hibernate对抗......继续使用复合键。如果您想要更轻松的生活,请确保每个表都有一个主键列。相信我,这不值得战斗......这是一场未来会花费你很多时间的战斗
  • “主键的一部分”是什么意思? Hibernate 中的复合主键非常简单,但您不应该尝试仅使用其中的一部分来使之复杂化。基本上你需要一个复合键类。这里有一个包含所有基本细节的答案:stackoverflow.com/questions/3585034/…
  • 这里有一个相当彻底的答案:stackoverflow.com/a/3588400/3166303
  • 对于一对多映射,您不需要复合键。在不使用复合键的情况下管理这种情况是如此容易。
  • @LanceJava 在这种情况下,由于可读性,我需要使用复合键。

标签: java hibernate foreign-keys composite-key composite-primary-key


【解决方案1】:

Jagger 的第二个解决方案是我的第一反应,@EmbededId 和@MapsId。以下是基于他的第二种解决方案但不使用@MapsId 的另一种方式。 `

@Entity
class A {
  @Id
  private int b;
  @Id
  private int c;
}

@Embeddable
class BKey {
  private int a;
  private int b;
}

@Entity
class B {
  @EmbeddedId
  private BKey primaryKey;

  @ManyToOne(optional = false)
  @JoinColumns(value = {
          @JoinColumn(name = "b", referencedColumnName = "b", insertable= false, updatable= false),
          @JoinColumn(name = "c", referencedColumnName = "c") }, )
  private A entityA;
}

【讨论】:

  • 这不起作用并以异常结束 org.hibernate.AnnotationException: Mixing insertable and non insertable columns in a property is not allowed 有一个 Hibernate bug
【解决方案2】:

我已经找到了解决这个问题的两种方法。

第一个是一种解决方法,不如第二个那么整洁。

B 实体的主键定义为包含col_acol_bcol_c 的复合键,并且首先应该是主键,定义为唯一约束。缺点是col_c 列在概念上并不是主键的一部分。

@Entity
class A {
  @Id
  private int b;
  @Id
  private int c;
}

@Entity
@Table(uniqueConstraints = {@UniqueConstraint(columnNames = { "a", "b" }) })
class B {
  @Id
  private int a;

  @Id
  @ManyToOne(optional = false)
  @JoinColumns(value = {
          @JoinColumn(name = "b", referencedColumnName = "b"),
          @JoinColumn(name = "c", referencedColumnName = "c") })
  private A entityA;
}

第二个使用@EmbeddedId@MapsId 注释,完全符合我一开始就想做的事情。

@Entity
class A {
  @Id
  private int b;
  @Id
  private int c;
}

@Embeddable
class BKey {
  private int a;
  private int b;
}

@Entity
class B {
  @EmbeddedId
  private BKey primaryKey;

  @MapsId("b")
  @ManyToOne(optional = false)
  @JoinColumns(value = {
          @JoinColumn(name = "b", referencedColumnName = "b"),
          @JoinColumn(name = "c", referencedColumnName = "c") })
  private A entityA;
}

【讨论】:

  • 要完成上述代码工作,您还需要为上述所有类实现 Serializable
  • 我试过这种方式,我得到了Unable to find column reference in the @MapsId mapping: c。任何想法?。 TIA
  • 是运行时错误还是编译错误?你能把你的代码贴在某个地方让我看看吗?
  • 两个属性可以有 MapsId 吗?例如,如果有一个属性“d”也是两个键的一部分(与 b 相同)?
  • 不幸的是,同一属性上不可能有多个“@MapsId”注释。但是我设法通过使用'@JoinFormula'而不是'@JoinColumn'来解决我的用例,用于主键和外键中使用的列。
猜你喜欢
  • 1970-01-01
  • 2015-08-20
  • 1970-01-01
  • 1970-01-01
  • 2013-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-15
相关资源
最近更新 更多