Could someone please help me with doing the bi-directional one-to-one JPA mapping for the following relationship using the composite primary key using Hibernate/JPA?
You can use an @Embeddable
to map the composite primary key of both entities and a @MapsId
annotation on the address attribute of your User
entity to share the primary key.
But before I show you the mapping, please be aware that User
is a reserved word in most databases. I recommend you choose a different name for the entity. In my example, I changed it to Person
.
Let's start with the @Embeddable
that maps the primary keys. I named the class AddressKey
. It's a simple Java class that implements the Serializable
interface and has the attributes xId
and yId
. You also need to implement the equals
and hashCode
methods.
@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;
}
}
If you annotate the attribute with @EmbeddedId
, you can use the AddressKey
embeddable to map the primary key of the 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
}
The mapping of the Person
entity looks similar. In addition to the primary key mapping, you need to annotate the address
attribute, which maps the association to the Person
entity, with @MapsId
. That tells Hibernate that it shall use the primary key of the associated Address
entity as the primary of the Person
entity.
You also need to annotate the address
attribute with 2 @JoinColumn
annotations to map the foreign keys to the xId
and yId
columns of your Person table. Without these annotations, Hibernate would map them to the columns address_xId
and 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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With