【问题标题】:Hibernate - Composite Primary Key contains Foreign KeyHibernate - 复合主键包含外键
【发布时间】:2018-01-07 04:48:37
【问题描述】:

我有一个类似的问题如下,但解决方案没有解决我的问题。

hibernate composite Primary key contains a composite foreign key, how to map this

我正在尝试加入 2 个表,每个表都有一个带有部分外键引用的复合主键。

Table A
--------
f1 (pk)
f2 (pk)
f3 (pk)
f4 (pk)

Table B
--------
f1 (pk, fk)
f2 (pk, fk)
f5 (pk)
f6 (pk)

I created A, APK, B, BPK

在 A 中:

private Set<B> bSet;
@OneToMany(targetEntity=B.class, cascade = CascadeType.ALL, mappedBy= "bpk.a")    
public Set<MovesEntity> getBSet() {
    return bSet;
}

在 BPK 中:

@ManyToOne(fetch=FetchType.EAGER)
@JoinColumns({
    @JoinColumn(name="f1", referencedColumnName="f1", nullable=false, insertable=false, updatable = false),
    @JoinColumn(name="f2", referencedColumnName="f2", nullable=false, insertable=false, updatable = false)
})
public A getA() {
    return a;
}

上述方法给了我这个例外:

AnnotationException: referencedColumnNames(f1, f2) of entity.BPK.bpk.a 
referencing com.example.entity.A not mapped to a single property

你能帮忙吗?

【问题讨论】:

  • JPA 不允许部分主键。 B 需要 A 的每个主键字段的外键来唯一标识 A。如果只有 f1 和 f2 唯一标识 A,那么它们应该是它的主键(而不是 f2 和 f3)。
  • 非常感谢克里斯。这解决了我的问题!.. 在这种情况下,我必须在 APK 中将 f3 和 f4 注释为 @Basic 而不是 id 或 embeddedId。我只将此服务用于 SELECT,所以我想它可以吗?
  • f3 和 f4 不应在 APK 中,而应在 A 中作为基础。
  • 是的,作为 A 中的 Basic - 谢谢!

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


【解决方案1】:

假设 f1 和 F2 唯一标识 A 并且存在于 APK 中,您可以通过几种方式为此使用 JPA 2.0 的派生 ID。最容易显示的是:

@Entity
@IdClass(BPK.class)
public class B {
  @ID
  String f5;
  @ID
  String f6;
  @ID
  @ManyToOne(fetch=FetchType.EAGER)
  @JoinColumns({
    @JoinColumn(name="f1", referencedColumnName="f1", nullable=false),
    @JoinColumn(name="f2", referencedColumnName="f2", nullable=false)
  })
  A a;
}

public class BPK {
  String f5;
  String f6;
  APK a;
}

这里的关键点是 B 对 A 的引用控制了外键字段 f1 和 f2,并且 A 的主键在 B 的主键中使用 - 与关系同名。映射它的另一种方法是将 B 的 PK 设为嵌入 id,但嵌入的 ID 仍然不能有引用映射,所以它可能看起来:

@Entity
@IdClass(BPK.class)
public class B {
  @EmbeddedId
  BPK pk;
  @MapsId("apk")
  @ManyToOne(fetch=FetchType.EAGER)
  @JoinColumns({
    @JoinColumn(name="f1", referencedColumnName="f1", nullable=false),
    @JoinColumn(name="f2", referencedColumnName="f2", nullable=false)
  })
  A a;
}

@Embeddable
public class BPK {
  String f5;
  String f6;
  APK apk;
}

注意 mapsId - 这告诉 JPA 嵌入的“apk”引用中的列使用从 A 中提取的引用映射中的外键字段。JPA 将从引用映射中为您填充外键,如果您正在使用排序。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-06
    • 2018-02-02
    • 2020-02-19
    • 2015-05-25
    相关资源
    最近更新 更多