π 1οΈβ£ Unidirectional @OneToOne Relationship
β
In a unidirectional @OneToOne, only one entity knows about the other, and the foreign key is stored in the owning entity.
π Example: A User has a Profile
- A User has exactly one Profile.
- A Profile belongs to exactly one User.
- The foreign key (
profile_id) is stored in theUsertable.
πΉ Step 1: Define the Owning Side (@OneToOne with @JoinColumn)
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
@OneToOne
@JoinColumn(name = "profile_id") // β
Foreign key stored in User table
private Profile profile;
}
-
@JoinColumn(name = "profile_id")ensures that theUsertable stores the foreign key.
πΉ Step 2: Define the Profile Entity (No Reference Back)
@Entity
public class Profile {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String bio;
}
-
Profiledoes not referenceUser(unidirectional). -
Userowns the relationship and has theprofile_idcolumn.
πΉ Generated SQL
CREATE TABLE user (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255),
profile_id BIGINT UNIQUE, -- β
Foreign key stored here
FOREIGN KEY (profile_id) REFERENCES profile(id)
);
CREATE TABLE profile (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
bio VARCHAR(255)
);
β
The profile_id foreign key is stored in User, ensuring a one-to-one relationship.
π Saving Data in Hibernate
Profile profile = new Profile();
profile.setBio("Software Engineer");
User user = new User();
user.setUsername("JohnDoe");
user.setProfile(profile); // β
Link profile to user
entityManager.persist(profile); // β
Save Profile first
entityManager.persist(user); // β
Then save User
π Now the User is linked to the Profile.
π Querying Data
User user = entityManager.find(User.class, 1L);
System.out.println(user.getProfile().getBio()); // β
Works!
β
You can access the Profile from User, but not the other way around.
π 2οΈβ£ Bidirectional @OneToOne Relationship
β
In a bidirectional @OneToOne, both entities know about each other.
π Example: A User has a Profile, and a Profile belongs to a User
-
User owns the relationship (
@OneToOnewith@JoinColumn). -
Profile has a reference back to User (
@OneToOne(mappedBy = "profile")).
πΉ Step 1: Define the Owning Side (@OneToOne with @JoinColumn)
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
@OneToOne
@JoinColumn(name = "profile_id") // β
Foreign key stored in User
private Profile profile;
}
β
User owns the relationship and has the foreign key.
πΉ Step 2: Define the Inverse Side (@OneToOne(mappedBy = "profile"))
@Entity
public class Profile {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String bio;
@OneToOne(mappedBy = "profile") // β
Inverse side
private User user;
}
β
mappedBy = "profile" tells Hibernate:
- "The foreign key is already in the
Usertable." - "Don't create another column in
Profile."
πΉ Generated SQL
CREATE TABLE user (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255),
profile_id BIGINT UNIQUE, -- β
Foreign key stored here
FOREIGN KEY (profile_id) REFERENCES profile(id)
);
CREATE TABLE profile (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
bio VARCHAR(255)
);
β
The foreign key is only in User.profile_id, keeping the relationship correct.
π Saving Data in Hibernate
Profile profile = new Profile();
profile.setBio("Software Engineer");
User user = new User();
user.setUsername("JohnDoe");
user.setProfile(profile);
profile.setUser(user); // β
Set reference back
entityManager.persist(profile); // β
Save Profile first
entityManager.persist(user); // β
Then save User
π Now, both User and Profile reference each other.
π Querying Both Directions
β User β Profile
User user = entityManager.find(User.class, 1L);
System.out.println(user.getProfile().getBio()); // β
Works!
β Profile β User
Profile profile = entityManager.find(Profile.class, 1L);
System.out.println(profile.getUser().getUsername()); // β
Works!
β Unlike the unidirectional version, now you can access both User β Profile and Profile β User.
π 3οΈβ£ Summary: Unidirectional vs. Bidirectional @OneToOne
| Feature | Unidirectional (@OneToOne) |
Bidirectional (@OneToOne + mappedBy) |
|---|---|---|
@OneToOne used? |
β Yes | β Yes (Both Sides) |
@JoinColumn used? |
β Yes (Owning Side) | β Yes (Owning Side) |
mappedBy used? |
β No | β Yes (Inverse Side) |
| Foreign key location? | In owning entity's table | In owning entity's table |
| Reference back? | β No | β Yes (Both Can Access Each Other) |
β
Best Practice: Use bidirectional @OneToOne if you need to query from both entities.
π Unidirectional @OneToOne is simpler if you only query in one direction.
π― Final Takeaways
-
Unidirectional
@OneToOne= Only one entity knows about the other (@JoinColumnin the owning side). -
Bidirectional
@OneToOne= Both entities reference each other (mappedByused on the inverse side). - Always place the foreign key on the entity that owns the relationship.
- Use bidirectional if you need to query both ways.
Top comments (0)