Spring Boot @OneToOne Mapping Explained: Unidirectional and Bidirectional Relationships
Image by Cloé Gérard from Pixabay

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

  • A Delegate has one Vote
  • The Delegate entity is the owner of this relationship
  • It is unidirectional; as you can see, the @OneToOne annotation is written in the Delegate class which references the Vote entity

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

  • TruckDriver is the owner of the relationship
  • TruckDriver will have a ‘driver_profile_id’ foreign key referencing the primary key of DriverProfile
  • The DriverProfile entity is mapped by the ‘driverProfile’ field in the ‘TruckDriver’ entity.
  • The mappedBy attribute tells Hibernate that the relationship is already managed by the TruckDriver entity and prevents duplicate foreign key columns from being created.

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.


To view or add a comment, sign in

More articles by Ifeakachukwu Osakwe

Explore content categories