具有复合主键的一对一双向映射
One-to-One bi-directional mapping with composite primary key
有人可以帮我使用 Hibernate/JPA 使用复合主键为以下关系执行双向一对一 JPA 映射吗?
您可以使用 @Embeddable
映射两个实体的复合主键,并在 User
实体的地址属性上使用 @MapsId
注释来共享主键。
但在我向您展示映射之前,请注意 User
是大多数数据库中的保留字。我建议您为该实体选择一个不同的名称。在我的示例中,我将其更改为 Person
.
让我们从映射主键的 @Embeddable
开始。我将 class 命名为 AddressKey
。它是一个简单的 Java class,实现了 Serializable
接口并具有属性 xId
和 yId
。您还需要实施 equals
和 hashCode
方法。
@Embeddable
public class AddressKey implements Serializable {
private Long xId;
private Long yId;
public AddressKey() {}
public AddressKey(Long xId, Long yId) {
this.xId = xId;
this.yId = yId;
}
// omit getter and setter for readability
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((xId == null) ? 0 : xId.hashCode());
result = prime * result + ((yId == null) ? 0 : yId.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
AddressKey other = (AddressKey) obj;
if (xId == null) {
if (other.xId != null)
return false;
} else if (!xId.equals(other.xId))
return false;
if (yId == null) {
if (other.yId != null)
return false;
} else if (!yId.equals(other.yId))
return false;
return true;
}
}
如果用 @EmbeddedId
注释属性,则可以使用 AddressKey
嵌入来映射 Address
class.
的主键
@Entity
public class Address {
@EmbeddedId
private AddressKey id;
private String city;
private String street;
private String country;
@OneToOne(mappedBy = "address")
private Person person;
// omit getter and setter methods
}
Person
实体的映射看起来很相似。除了主键映射,还需要注解address
属性,将关联映射到Person
实体,用@MapsId
。这告诉 Hibernate 它应该使用关联的 Address
实体的主键作为 Person
实体的主键。
您还需要使用 2 个 @JoinColumn
注释来注释 address
属性,以将外键映射到您的 Person xId
和 yId
列 table.如果没有这些注释,Hibernate 会将它们映射到列 address_xId
和 address_yId
.
@Entity
public class Person {
@EmbeddedId
private AddressKey id;
private String name;
private String society;
@OneToOne
@JoinColumn(name="xId", referencedColumnName="xId")
@JoinColumn(name="yId", referencedColumnName="yId")
@MapsId
private Address address;
// omit getter and setter methods for readability
}
有人可以帮我使用 Hibernate/JPA 使用复合主键为以下关系执行双向一对一 JPA 映射吗?
您可以使用 @Embeddable
映射两个实体的复合主键,并在 User
实体的地址属性上使用 @MapsId
注释来共享主键。
但在我向您展示映射之前,请注意 User
是大多数数据库中的保留字。我建议您为该实体选择一个不同的名称。在我的示例中,我将其更改为 Person
.
让我们从映射主键的 @Embeddable
开始。我将 class 命名为 AddressKey
。它是一个简单的 Java class,实现了 Serializable
接口并具有属性 xId
和 yId
。您还需要实施 equals
和 hashCode
方法。
@Embeddable
public class AddressKey implements Serializable {
private Long xId;
private Long yId;
public AddressKey() {}
public AddressKey(Long xId, Long yId) {
this.xId = xId;
this.yId = yId;
}
// omit getter and setter for readability
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((xId == null) ? 0 : xId.hashCode());
result = prime * result + ((yId == null) ? 0 : yId.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
AddressKey other = (AddressKey) obj;
if (xId == null) {
if (other.xId != null)
return false;
} else if (!xId.equals(other.xId))
return false;
if (yId == null) {
if (other.yId != null)
return false;
} else if (!yId.equals(other.yId))
return false;
return true;
}
}
如果用 @EmbeddedId
注释属性,则可以使用 AddressKey
嵌入来映射 Address
class.
@Entity
public class Address {
@EmbeddedId
private AddressKey id;
private String city;
private String street;
private String country;
@OneToOne(mappedBy = "address")
private Person person;
// omit getter and setter methods
}
Person
实体的映射看起来很相似。除了主键映射,还需要注解address
属性,将关联映射到Person
实体,用@MapsId
。这告诉 Hibernate 它应该使用关联的 Address
实体的主键作为 Person
实体的主键。
您还需要使用 2 个 @JoinColumn
注释来注释 address
属性,以将外键映射到您的 Person xId
和 yId
列 table.如果没有这些注释,Hibernate 会将它们映射到列 address_xId
和 address_yId
.
@Entity
public class Person {
@EmbeddedId
private AddressKey id;
private String name;
private String society;
@OneToOne
@JoinColumn(name="xId", referencedColumnName="xId")
@JoinColumn(name="yId", referencedColumnName="yId")
@MapsId
private Address address;
// omit getter and setter methods for readability
}