What is @OneToOne Mapping in JPA?
@OneToOne is a JPA annotation used to define a one-to-one relationship between two entity classes.
It means:
βOne record in one table is associated with exactly one record in another table.β
In simple words:
- One entity β One related entity
- One database row β One related row
Real-Life Example of One-to-One Relationship
Consider:
- One person has one passport
- One employee has one ID card
- One user has one profile
These are examples of one-to-one relationships.
Database Example
users Table
| id | name |
|---|---|
| 1 | Naresh |
profiles Table
| id | address | user_id |
|---|---|---|
| 10 | Hyderabad | 1 |
Here:
- One user has one profile
- One profile belongs to one user
Why @OneToOne Mapping is Needed
Without relationships:
- Developers must manually write joins
- Object navigation becomes difficult
- Complex SQL queries increase
@OneToOne simplifies:
- Entity relationships
- Database joins
- Object navigation
- Automatic fetching
Basic @OneToOne Example
User Entity
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToOne
@JoinColumn(name = "profile_id")
private Profile profile;
}
Profile Entity
@Entity
public class Profile {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String address;
}
What Does @JoinColumn Mean?
@JoinColumn specifies the foreign key column used for relationship mapping.
Example
@JoinColumn(name = "profile_id")
means:
profile_id
is the foreign key column in the database.
Generated Database Structure
users Table
CREATE TABLE users (
id BIGINT PRIMARY KEY,
name VARCHAR(255),
profile_id BIGINT,
FOREIGN KEY (profile_id)
REFERENCES profiles(id)
)
How @OneToOne Works Internally
- Hibernate detects relationship annotations
- Foreign key mapping is created
- SQL joins are generated automatically
- Related entities are fetched when needed
Saving One-to-One Data
Profile profile = new Profile();
profile.setAddress("Hyderabad");
User user = new User();
user.setName("Naresh");
user.setProfile(profile);
userRepository.save(user);
Generated SQL Example
INSERT INTO profiles(address)
VALUES ('Hyderabad');
INSERT INTO users(name, profile_id)
VALUES ('Naresh', 1);
Fetch Data Example
User user = userRepository.findById(1L).get();
System.out.println(
user.getProfile().getAddress()
);
Types of One-to-One Mapping
JPA supports:
- Unidirectional mapping
- Bidirectional mapping
1. Unidirectional One-to-One Mapping
Only one entity knows about the relationship.
Example
@OneToOne
private Profile profile;
User knows Profile, but Profile does not know User.
2. Bidirectional One-to-One Mapping
Both entities know about each other.
Bidirectional Example
User Entity
@Entity
public class User {
@Id
private Long id;
@OneToOne(mappedBy = "user")
private Profile profile;
}
Profile Entity
@Entity
public class Profile {
@Id
private Long id;
@OneToOne
@JoinColumn(name = "user_id")
private User user;
}
What Does mappedBy Mean?
mappedBy specifies:
- Which entity owns the relationship
- Avoids duplicate foreign keys
Owning Side vs Inverse Side
| Type | Description |
|---|---|
| Owning Side | Contains @JoinColumn |
| Inverse Side | Contains mappedBy |
Fetch Types in @OneToOne
JPA supports:
- EAGER fetching
- LAZY fetching
EAGER Fetch Example
@OneToOne(fetch = FetchType.EAGER)
Related entity loads immediately.
LAZY Fetch Example
@OneToOne(fetch = FetchType.LAZY)
Related entity loads only when accessed.
EAGER vs LAZY
| Feature | EAGER | LAZY |
|---|---|---|
| Loading Time | Immediate | On demand |
| Performance | Can be slower | Usually better |
| Memory Usage | Higher | Lower |
Cascade Types in @OneToOne
Cascade operations automatically apply actions to related entities.
Cascade Example
@OneToOne(
cascade = CascadeType.ALL
)
What CascadeType.ALL Does
When User is saved:
- Profile is also saved automatically
Advantages of @OneToOne Mapping
- Simplifies relationships
- Automatic joins
- Easy object navigation
- Reduces manual SQL
- Improves maintainability
Disadvantages of Improper One-to-One Mapping
- Performance issues
- Excessive eager loading
- Circular references
- Complex debugging
Best Practices for @OneToOne
- Use LAZY fetching when possible
- Use cascade carefully
- Avoid unnecessary bidirectional mapping
- Use proper foreign key naming
- Prevent circular serialization issues
Real-Time Example in Banking Application
Banking application may contain:
- One customer β One KYC document
- One account β One debit card
- One user β One security profile
These relationships are implemented using:
@OneToOne
Difference Between @OneToOne and @OneToMany
| Feature | @OneToOne | @OneToMany |
|---|---|---|
| Relationship | One to one | One to many |
| Example | User β Profile | Customer β Orders |
| Foreign Key Count | Single relationship | Multiple related records |
Common Interview Questions on @OneToOne
What is @OneToOne mapping?
It defines a one-to-one relationship between two entities.
What is @JoinColumn?
It specifies the foreign key column used in the relationship.
What is mappedBy?
It specifies the inverse side of the relationship.
What is the difference between unidirectional and bidirectional mapping?
Unidirectional allows one-way navigation, while bidirectional allows both entities to reference each other.
Which fetch type is better?
LAZY fetching is usually preferred for better performance.
Conclusion
@OneToOne is an important JPA relationship annotation
used to map one-to-one relationships between entities.
It simplifies:
- Relationship handling
- Database joins
- Object navigation
- Automatic fetching
Understanding @OneToOne is essential for Spring Boot developers
because enterprise applications heavily rely on entity relationships
for proper database design and object mapping.