hibernate composite主键包含一个复合外键,如何映射这个

我在那里搜索,没有找到任何类似的话题,所以我发布了一个新问题。

我正在使用现有数据库上的Hibernate。 我们不允许更改表结构和数据。 应用程序正在从数据库中读取数据,并根据某些逻辑迁移到另一个数据存储区。

现在的问题是关于复合PK映射。 例如

表A具有复合PK。

Table A -------- a1 (pk) a2 (pk) a3 (pk) a4 (pk) foo bar ======== 

表B也具有复合PK,并且该复合PK的一部分是A的PK,这里也用作FK。

 Table B -------- a1 (fk,pk) a2 (fk,pk) a3 (fk,pk) a4 (fk,pk) b1 (pk) b2 (pk) b3 (pk) foo bar ======== 

我尝试了几种方法,但没有一种方法可行。 谁能告诉一个有效的Hibernate映射解决方案? 注释风格更好。

将A的实体对象设置为B的pk类中的@ManyToOne。

所以,如果你有

 Class A Class APK - A's Primary Key Class B Class BPK - B's primary Key. 

BPK将包含A作为属性

 @Embeddable public class BPK implements serializable { .... private A a; @ManyToOne(fetch=FetchType.EAGER) @JoinColumns ({ @JoinColumn(name="...", referencedColumnName = "..."), @JoinColumn(name="...", referencedColumnName = "..."), ... }) public getA() { return this.a; } } 

从文档中

除非使用Hibernate特定注释@AccessType,否则@Embeddableinheritance其拥有实体的访问类型。 复合外键(如果不使用默认敏感值)是在使用@JoinColumns元素的关联上定义的,该元素基本上是@JoinColumn的数组。 明确表达referencedColumnNames是一种很好的做法。 否则,Hibernate将假设您使用与主键声明中相同的列顺序。

如果复合主键只有代理键,请使用@EmbeddableId

 @Embeddable public class CompoundIdA implements Serializable { private Integer field0; private Integer field1; private Integer field2; private Integer field3; @Column(name="FIELD_0") public Integer getField0() { return this.field0; } @Column(name="FIELD_1") public Integer getField1() { return this.field1; } @Column(name="FIELD_2") public Integer getField2() { return this.field2; } @Column(name="FIELD_3") public Integer getField3() { return this.field3; } public boolean equals(Object o) { if(o == null) return false; if(!(o instanceof CompoundIdA)) return false; final CompoundIdA other = (CompoundIdA) o; if(!(getField0().equals(other.getField0())) return false; if(!(getField1().equals(other.getField1())) return false; if(!(getField2().equals(other.getField2())) return false; if(!(getField2().equals(other.getField2())) return false; return true; } // hashcode impl } 

在ClassA中,我们有

 @Entity public class ClassA { private CompoundIdA compoundIdA; @EmbeddedId public CompoundIdA getCompoundIdA() { return this.CompoundIdA; } } 

如果复合主键同时具有自然键和代理键 ,请再次使用@EmbeddableId

 // Let's suppose field0 and field1 are both natural keys @Entity public class ClassA { private CompoundIdA compoundIdA; private Integer field0; private Integer field1; @EmbeddedId public CompoundIdA getCompoundIdA() { return this.CompoundIdA; } @Column(name="FIELD_0", insertable=false, updateable=false) public Integer getField0() { return this.field0; } @Column(name="FIELD_1", insertable=false, updateable=false) public Integer getField1() { return this.field1; } } 

请注意, 您必须设置insertable = false和updateable = false,因为多个属性共享同一列。 否则,Hibernate会抱怨一些错误。

如果复合主键只有自然键,请使用@IdClass

 @Entity @IdClass(CompoundIdA.class) public class ClassA { private Integer field0; private Integer field1; private Integer field2; private Integer field3; @Id @Column(name="FIELD_0") public Integer getField0() { return this.field0; } @Id @Column(name="FIELD_1") public Integer getField1() { return this.field1; } @Id @Column(name="FIELD_2") public Integer getField2() { return this.field2; } @Id @Column(name="FIELD_3") public Integer getField3() { return this.field3; } } 

在ClassB中,您可以使用与上面所示相同的方法, 但是如果要定义@ManyToOne属性, 则必须设置 insertable = false和updateable = false,如下所示

 @Entity public class ClassB { private ClassA classA; @ManyToOne @JoinColumns ({ @JoinColumn(name="FIELD_0", referencedColumnName="FIELD_0", insertable=false, updateable=false), @JoinColumn(name="FIELD_1", referencedColumnName="FIELD_1", insertable=false, updateable=false), @JoinColumn(name="FIELD_2", referencedColumnName="FIELD_2", insertable=false, updateable=false), @JoinColumn(name="FIELD_3", referencedColumnName="FIELD_3", insertable=false, updateable=false) }) public ClassA getClassA() { return this.classA; } } 

问候,