Careeroza
LazyInitializationException
The Most Famous Hibernate Error
A lazy proxy can load its data only while the persistence context (Session) is open, which in Spring means inside the @Transactional method. Touch it after the transaction ends and you get:
Example
public Order getOrder(Long id) { // no @Transactional
return orderRepository.findById(id).orElseThrow();
}
// in the controller:
order.getItems().size();Example output
org.hibernate.LazyInitializationException: Cannot lazily initialize collection of role 'com.shopease.order.Order.items' with key '501' (no session) org.hibernate.LazyInitializationException: Could not initialize proxy [com.shopease.catalog.Category#3] - no session
Why It Happens
Controller ──► OrderService.getOrder() ──► repository.findById()
│ transaction + Session open
│ Order loaded, items = uninitialized collection
▼ transaction ends, Session closed, Order is now DETACHED
Controller: order.getItems().size() ──► no Session to run SELECT ──► LazyInitializationExceptionCorrect Fixes
- Load what you need inside the transaction with a fetch join or
@EntityGraph(next topics). - Map to a DTO inside the service (the transaction is still open), and return the DTO to the controller.
- Use a DTO projection query that selects exactly the needed columns.
@Transactional(readOnly = true)
public OrderDetailsDto getOrder(Long id) {
Order order = orderRepository.findWithItemsById(id) // JOIN FETCH query
.orElseThrow(() -> new OrderNotFoundException(id));
return OrderDetailsDto.from(order); // mapped while the Session is open
}Fixes to Avoid
| "Fix" | Problem |
|---|---|
Change to FetchType.EAGER | every query now loads the association; causes N+1 elsewhere |
spring.jpa.open-in-view=true (Spring Boot default) | keeps the connection busy while the view/JSON renders; hides N+1 queries in controllers |
hibernate.enable_lazy_load_no_trans=true | opens a new connection and Session for every lazy access: N+1 with extra connections |
Calling Hibernate.initialize() everywhere | works, but runs one extra query per association |
Tip: Spring Boot logs a warning at startup: spring.jpa.open-in-view is enabled by default. Set spring.jpa.open-in-view=false in new projects so lazy-loading mistakes show up in development, not as slow pages in production.