Java — Hibernate LazyInitializationException outside a session
Fix LazyInitializationException by fetching the needed associations within the transaction or using DTOs.
Symptoms
- org.hibernate.LazyInitializationException: could not initialize proxy - no Session
- It works inside a service but fails during JSON serialization
- Accessing a collection after the transaction ends throws
- The exception appears in the controller or view layer
Possible causes
- A lazy association is accessed after the session or transaction closed
- The entity is returned outside the transactional boundary and serialized later
- Open Session in View is disabled
- The association was not fetched eagerly for this use case
Diagnosis steps
Locate where the association is accessed
grep -rn "getItems\|getOrders()\|@OneToMany\|@ManyToOne" srcInterpretation
Accessing the association outside the service transaction, such as in serialization, is the usual trigger.
Fetch within the transaction
join fetch / EntityGraph on the repository queryInterpretation
Fetching the association while the session is open loads it before the entity leaves the boundary.
Map to a DTO inside the transaction
orderMapper.toDto(order)Interpretation
A DTO populated inside the transaction carries plain data that needs no session later.
Root cause
A lazily loaded association was accessed after its persistence context closed, so Hibernate had no session to run the loading query and raised LazyInitializationException.
Fix
Fetch the associations you need within the transaction using join fetch or an entity graph, or return DTOs built inside the transaction instead of detached entities.
Verify the fix
Exercise the same request and confirm the association loads without the exception, and confirm the returned data contains the expected related rows.
Symptom walkthrough
Accessing a mapped association after the transaction ends throws LazyInitializationException: could not initialize proxy - no Session. It typically appears in the controller, view or JSON serialization layer, while the same data loads fine inside the service method. The entity left the persistence context and its lazy associations can no longer be initialized on demand.
Fix in practice
Fetch the needed associations inside the transaction with a join fetch or an entity graph, or map entities to DTOs before the transaction closes. This keeps all required data loaded while a session is available. Enabling open-session-in-view hides the problem and can hold connections open longer, so prefer explicit fetching.
Verification
Repeat the request and confirm the association loads without the exception and that the response contains the expected related data. Loading correctly, not merely not throwing, confirms the fetch strategy is right.
Diagnostic commands
Check the behavior with commands like these:
grep -rn "getItems\|getOrders()\|@OneToMany\|@ManyToOne" src
join fetch / EntityGraph on the repository query
orderMapper.toDto(order)