Java hibernate复合主键包含复合外键,如何映射
我在那里搜索,没有找到任何类似的主题,所以我发布了一个新问题 我正在现有数据库上使用Hibernate。我们不允许更改表结构和数据。应用程序正在从数据库读取数据,并根据某些逻辑迁移到另一个数据存储 现在的问题是关于复合PK映射。e、 g 表A有一个复合PKJava hibernate复合主键包含复合外键,如何映射,java,hibernate,hibernate-annotations,Java,Hibernate,Hibernate Annotations,我在那里搜索,没有找到任何类似的主题,所以我发布了一个新问题 我正在现有数据库上使用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
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映射解决方案?注释样式更好。在B的pk类中将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;
}
}
从
@Embeddeble继承的访问类型为
它所拥有的实体,除非休眠
特定注释@AccessType为
用过。复合外键(如果不是
使用默认敏感值)
使用
@JoinColumns元素,它是
基本上是@JoinColumn的数组。信息技术
这被认为是一个很好的实践
表示引用的列名称
明确地否则,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
}
// 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;
}
}
在A班,我们有
@Entity
public class ClassA {
private CompoundIdA compoundIdA;
@EmbeddedId
public CompoundIdA getCompoundIdA() {
return this.CompoundIdA;
}
}
如果复合主键同时具有自然键和代理键,请再次使用@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
}
// 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中,您可以使用与上面所示相同的方法,但是如果您想要定义@manytone属性,您必须设置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;
}
}
您好,我真的看不出您的答案和我的答案有什么不同。除了您对我概述的相同内容使用了替代注释之外。我如何为相同内容编写ClassB.hbm.xml?@Vinodh Ramasubramania嗨,使用实体作为主键不是一个好主意。Hibernate团队确实推荐。不能跨用作主键的实体限制HQL中的查询结果或条件。因此,有很多方法可以避免使用它,但我不使用实体作为PK。我使用它(A)与B的PK中的连接条件建立多通关系。在您的解决方案中,我看不出B的复合PK(BPK)是如何定义为A的复合PK(APK)的子集的。BPK类中的一通可以帮助我。我没有朝那个方向想。我一直在想如何引用BPK中的另一个APK类。不知道如何设置注释。为了方便起见,我在一个类中建模了另一个带有joincolumns的One2Many。e、 g.专用集bSet;。在TypeB类中,也是一个指向TypeA的多音字。当然,需要insertable、updateable=false。谢谢你们。