I am analysing a "classic" Hibernate error :
org.hibernate.LazyInitializationException : could not initialize proxy – no Session.
I am wondering how it could happen whereas the Spring Open In View mode is enabled?
If you have any documentation or knowledge on a possible reason, please share. Thanks
CodePudding user response:
Here is the documentation from the latest hibernate version.
As you can see
Indicates an attempt to access not-yet-fetched data outside of a session context. For example, when an uninitialized proxy or collection is accessed after the session was closed.
Most probably somewhere you read some entity and then outside of a transaction you try to read some collection which was by default lazy loaded. So then another request needs to be done to database, but since you are out of transaction you receive this exception.
This usually occurs in case you load an entity without the annotation @Transactional
or some other configuration to load it inside a transaction and then you give this to your controller
to be returned to the user. Then the controller will use jackson
or some other library to convert the entity
object into a json
and will try to read any field. At this point trying to read any lazy loaded collections from the entity, will result in this exception since the read will be outside of a transaction.
CodePudding user response:
Here are some feebacks on my context, and an example of what could cause LazyInitializationException
event if Spring Open In View is enabled.
Context
My application is a REST API server developed with Spring Boot 2.5.3.
Spring Open In View is kept enabled by default.
A lot of Services are annotated with @Transactional
methods.
Spring-data is used, and Entitymanager
too, to create some native queries.
The error
One REST API request, that generates a lot requests to the database (both selections and insertions), fails with LazyInitializationException
.
Debugging
By setting a breakpoint when LazyInitializationException
is thrown, I discovered that the exception is thrown in org.hibernate.proxy.AbstractLazyInitializer#initialize
, because the session
is null. Then I discovered that the session
is set to null, when the method EntityManager.clear
is called. For any reason I don't know, this method was explicitely called in the code.
Fixing
So I just removed the call to EntityManager.clear
, and the request works. I'm still wondering why previous developers wanted to clear the EntityManager
, probably because they were confused with the transaction management.
Conclusion
Even in Spring Open In View is enabled, and as a result, event if a Hibernate Session is opened, calling EntityManager.clear
unset the session to the entities loaded before. Then trying to access a Lazy Loaded field on those entities throws LazyInitializationException
.
I hope this will help someone.