我在那里搜索,但没有找到任何类似的话题,所以我发布了一个新问题。
我正在使用现有数据库上的Hibernate。我们不允许更改表结构和数据。应用程序正在从数据库中读取数据,并根据某些逻辑迁移到另一个数据存储区。
现在的问题是关于复合PK映射。 e.g。
表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映射解决方案?注释风格更好。
答案 0 :(得分:9)
在B的pk Class中将A的实体对象设置为@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;
}
}
@Embeddable继承了访问类型 它拥有的实体,除非Hibernate 特定注释@AccessType是 用过的。复合外键(如果没有 使用默认敏感值) 在使用的关联上定义 @JoinColumns元素,即 基本上是一个@JoinColumn数组。它 被认为是一种很好的做法 表达referencedColumnNames 明确。否则,Hibernate会 假设您使用相同的顺序 列中的列与主键中一样 声明。
答案 1 :(得分:3)
如果您的复合主键具有仅代理键,请使用@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;
}
}
的问候,