Spring Boot @OneToOne Mapping Explained: Unidirectional and Bidirectional Relationships
In Spring Boot, one-to-one mapping is one of the several types of entity relationships that you can define to model the association between entities
Here is the definition of @OneToOne mapping (from the Javadocs):
Specifies a single-valued association to another entity that has one-to-one multiplicity. It is not normally necessary to specify the associated target entity explicitly since it can usually be inferred from the type of the object being referenced…
We will see how it looks in code, and gain more clarity as we explain further.
Unidirectional Mapping
@Entity
public class Delegate {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToOne
private Vote vote;
}
@Entity
public class Vote {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String reference;
}
Explanation
When the database table is created by JPA/Hibernate, Delegate table is going to have a foreign key called ‘vote_id’, which is a pointer to the ‘id’ column of the Vote table.
Bidirectional Mapping
The definition of OneToOne mapping in the Javadocs continues by mentioning this:
...If the relationship is bidirectional, the non-owning side must use the mappedBy element of the OneToOne annotation to specify the relationship field or property of the owning side…
In a bidirectional mapping, both entities in a relationship are aware of each other. This means you can navigate the relationship from either side of the entities.
In the context of @OneToOne mapping, both entities will reference each other, and their relationship is synchronised.
Let us see how it looks in code
@Entity
public class TruckDriver {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToOne
private DriverProfile driverProfile;
}
@Entity
public class DriverProfile {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String bio;
@OneToOne(mappedBy = "driverProfile")
private TruckDriver truckDriver;
}
Explanation
With bidirectional mapping, you can access related entities from either side, writing code like this:
truckDriver.getDriverProfile();
driverProfile.getTruckDriver();
@JoinColumn is another annotation that gives you more control over how the foreign key is managed. The name property of the annotation specifies the column name you want for the foreign key.
What we have looked at is the @OneToOne mapping in its basic form. If you understand the basics well enough, you can then use supporting annotations like @JoinColumn to customise things to your taste.