🚀 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)