How to Fix Lazy Initialization Exception in Spring Boot
LazyInitializationException in Spring Boot happens when you try to access a lazy-loaded entity outside of an active session or transaction. To fix it, ensure the entity is fetched within a transaction or use fetch = FetchType.EAGER or JOIN FETCH queries to load related data eagerly.Why This Happens
This exception occurs because Spring uses lazy loading by default for related entities. When you try to access a lazy-loaded property after the database session is closed, Spring cannot fetch the data and throws LazyInitializationException.
import jakarta.persistence.*; import java.util.List; @Entity public class User { @Id private Long id; @OneToMany(fetch = FetchType.LAZY) private List<Order> orders; // getters and setters } // In a service method @Transactional public User getUser(Long id) { User user = entityManager.find(User.class, id); return user; } // Later in controller or outside transaction User user = userService.getUser(1L); List<Order> orders = user.getOrders(); // Throws LazyInitializationException here
The Fix
To fix this, you can fetch the lazy collection inside the transaction or use eager fetching. One common way is to use JOIN FETCH in your query to load related entities eagerly before the session closes.
import jakarta.persistence.*; import java.util.List; @Entity public class User { @Id private Long id; @OneToMany(fetch = FetchType.LAZY) private List<Order> orders; // getters and setters } // In repository or DAO public User findUserWithOrders(Long id) { return entityManager.createQuery( "SELECT u FROM User u JOIN FETCH u.orders WHERE u.id = :id", User.class) .setParameter("id", id) .getSingleResult(); } // In service @Transactional public User getUserWithOrders(Long id) { return findUserWithOrders(id); } // Now accessing orders outside transaction works User user = userService.getUserWithOrders(1L); List<Order> orders = user.getOrders(); // No exception, orders loaded eagerly
Prevention
To avoid this error in the future, always access lazy-loaded properties within a transaction or use eager fetching when you know you need related data. Also, consider using DTOs with explicit queries to fetch only needed data. Avoid exposing entities directly to the view layer.
- Use
@Transactionalon service methods accessing lazy properties. - Use
JOIN FETCHqueries to load related entities eagerly. - Consider
FetchType.EAGERonly if it won't cause performance issues. - Use projections or DTOs to fetch required data explicitly.
Related Errors
Other errors related to lazy loading include:
- org.hibernate.ObjectNotFoundException: Happens when a proxy is accessed but the entity does not exist in the database.
- org.hibernate.HibernateException: No Session: Occurs when trying to access lazy data without an active Hibernate session.
- StackOverflowError: Can happen if bidirectional lazy relationships cause infinite loops during serialization.
Quick fixes include ensuring transactions are active, using DTOs, and managing serialization carefully.