π 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 theUser
table.
πΉ 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 theUser
table 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;
}
-
Profile
does not referenceUser
(unidirectional). -
User
owns the relationship and has theprofile_id
column.
πΉ 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 (
@OneToOne
with@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
User
table." - "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 (@JoinColumn
in the owning side). -
Bidirectional
@OneToOne
= Both entities reference each other (mappedBy
used 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)