What is Fetch Type in JPA?
Fetch Type in JPA defines how related entities should be loaded from the database.
It controls:
- When related data is fetched
- How Hibernate loads relationships
- Performance optimization
In simple words:
βFetch type decides whether related data loads immediately or only when needed.β
Why Fetch Type is Important
Enterprise applications often contain relationships such as:
- Customer β Orders
- Student β Courses
- User β Roles
Loading all related data every time may:
- Reduce performance
- Increase memory usage
- Slow database queries
Fetch type helps optimize these operations.
Types of Fetching in JPA
JPA provides two fetch types:
- EAGER Fetching
- LAZY Fetching
1. EAGER Fetching
In EAGER fetching, related entities are loaded immediately along with the parent entity.
EAGER Fetch Example
@ManyToOne(fetch = FetchType.EAGER)
private Department department;
How EAGER Fetching Works
Suppose:
- Employee belongs to Department
When Employee is loaded:
- Department is also loaded immediately
Generated SQL Example
SELECT e.*, d.*
FROM employees e
LEFT JOIN departments d
ON e.department_id = d.id
Advantages of EAGER Fetching
- Related data available immediately
- No additional query needed later
- Simpler object access
Disadvantages of EAGER Fetching
- Can reduce performance
- Loads unnecessary data
- Higher memory usage
- Complex joins for large relationships
2. LAZY Fetching
In LAZY fetching, related entities are loaded only when accessed explicitly.
LAZY Fetch Example
@OneToMany(fetch = FetchType.LAZY)
private List<Order> orders;
How LAZY Fetching Works
When Customer is loaded:
- Orders are NOT loaded immediately
- Orders load only when getOrders() is called
Example
Customer customer =
customerRepository.findById(1L).get();
customer.getOrders();
Orders are fetched only here.
Generated SQL Example
Initial Query
SELECT *
FROM customers
WHERE id = 1
Later Query
SELECT *
FROM orders
WHERE customer_id = 1
Advantages of LAZY Fetching
- Better performance
- Lower memory usage
- Loads data only when needed
- Efficient for large collections
Disadvantages of LAZY Fetching
- Additional queries may occur
- LazyInitializationException possible
- Debugging may become difficult
Default Fetch Types in JPA
| Relationship | Default Fetch Type |
|---|---|
| @OneToOne | EAGER |
| @ManyToOne | EAGER |
| @OneToMany | LAZY |
| @ManyToMany | LAZY |
Why Collections Use LAZY by Default
Collections may contain:
- Thousands of records
- Large object graphs
Immediate loading may hurt performance.
Real-Time Example
Suppose an e-commerce application contains:
- Customer
- Orders
One customer may have:
- 10,000 orders
Loading all orders every time is inefficient.
LAZY fetching solves this problem.
Entity Example with Fetch Types
Customer Entity
@Entity
public class Customer {
@Id
private Long id;
private String name;
@OneToMany(
mappedBy = "customer",
fetch = FetchType.LAZY
)
private List<Order> orders;
}
Order Entity
@Entity
public class Order {
@Id
private Long id;
@ManyToOne(
fetch = FetchType.EAGER
)
private Customer customer;
}
What is LazyInitializationException?
This exception occurs when:
- LAZY-loaded data is accessed
- Outside Hibernate session
Example
failed to lazily initialize a collection
Why LazyInitializationException Happens
Hibernate session closes before:
getOrders()
is called.
Solutions for LazyInitializationException
- Use JOIN FETCH queries
- Use transactional methods
- Use DTO projections
- Use Open Session in View carefully
JOIN FETCH Example
@Query("""
SELECT c
FROM Customer c
JOIN FETCH c.orders
WHERE c.id = :id
""")
Customer findCustomerWithOrders(Long id);
What is N+1 Query Problem?
N+1 problem occurs when:
- One query fetches parent entities
- Additional queries repeatedly fetch child entities
N+1 Example
List<Customer> customers =
customerRepository.findAll();
for (Customer customer : customers) {
customer.getOrders();
}
This may trigger multiple queries.
EAGER vs LAZY Comparison
| Feature | EAGER | LAZY |
|---|---|---|
| Loading Time | Immediate | On demand |
| Performance | Can be slower | Usually better |
| Memory Usage | Higher | Lower |
| Complexity | Simpler | More complex |
Best Practices for Fetch Types
- Prefer LAZY fetching for collections
- Avoid excessive EAGER loading
- Use DTOs for APIs
- Use JOIN FETCH carefully
- Optimize queries for performance
When to Use EAGER Fetching
- Small relationships
- Always-needed related data
- Critical parent-child access
When to Use LAZY Fetching
- Large collections
- Performance-sensitive systems
- Microservices
- REST APIs
Real-Time Example in Banking Application
Banking application contains:
- Customer
- Transactions
One customer may have:
- Millions of transactions
Loading all transactions immediately is inefficient, so LAZY fetching is preferred.
Advantages of Proper Fetch Strategy
- Better performance
- Reduced memory usage
- Optimized database queries
- Improved scalability
Disadvantages of Poor Fetch Strategy
- Slow application performance
- Excessive database queries
- Memory issues
- N+1 query problems
Common Interview Questions on Fetch Type
What is fetch type in JPA?
Fetch type defines when related entities should be loaded.
What are the two fetch types?
EAGER and LAZY.
Which fetch type is default for @OneToMany?
LAZY.
Which fetch type is default for @ManyToOne?
EAGER.
Which fetch type is better?
LAZY is usually preferred for better performance.
Conclusion
Fetch type is one of the most important concepts in JPA and Hibernate relationship management.
It controls:
- How related entities load
- Database query behavior
- Application performance
Choosing the correct fetch strategy is essential for building scalable and high-performance Spring Boot applications.
Understanding fetch types helps developers optimize:
- Database performance
- Memory usage
- Query execution
- Microservice scalability