I have been suffering from infamous hibernate exception
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
Now the community is cheering over
<property name="hibernate.enable_lazy_load_no_trans" value="true"/>
saying it solves the problem but USE IT WITH CAUTION.
What they mean by use it with caution? What this property actually does?
Please give me any insights. Thanks in advance.
The right way to fix a LazyInitializationException is to fetch all required associations within your service layer. The best option for that is to load the entity with all required associations in one query.
if you are using annotation configuration: add @Proxy(lazy=false) to all your entity classes. That's all about how to fix Exception in thread "main" org. hibernate. LazyInitializationException: could not initialize proxy - no Session.
Hibernate has a workaround, an enable_lazy_load_no_trans property. Turning this on means that each fetch of a lazy entity will open a temporary session and run inside a separate transaction.
Just make the lazy=false and hibernate will load the child when parent is loaded from the database. In the above configuration. If lazy="false" : - when you load the Employee object that time child object Address is also loaded and set to setAddresss() method. If you call employee.
The problem with this approach is that you can have the N+1 effect.
Imagine that you have the following entity:
public class Person{ @OneToMany // default to lazy private List<Order> orderList; }
If you have a report that returns 10K of persons, and if in this report you execute the code person.getOrderList()
the JPA/Hibernate will execute 10K of queries. This is the N+1 effect, you will have no control about all the queries that will be executed.
Imagine now that Order is like below:
public class Order{ @OneToMany // default to lazy private List<EmailSent> emailSentList; }
Imagine now that you have a iteration with the person.getOrderList()
and for every Order order
you will do a order.getEmailSentList()
. Can you see the problem now?
For LazyInitializationException you can have some solutions:
select p from Person p join fetch p.orderList
. With this query you will have your list loaded from the database and will not have the N+1 effect. The problem is that you will need to write a JPQL for each case.If you still have any problem, check these links:
This goes against how we can take advantage of Hibernate's enforcement of repeatable read semantics with the Session concept. When an object is first loaded and if the object is referenced again within the life of the session, then the same object is returned IRRESPECTIVE of whether this object has changed in the DB. This is the repeatable read semantics provided automatically by hibernate.
With this setting, you have no session providing this guarantee, so if you now access this data you will be getting the latest version of the data.
This might be fine. But consider the scenario where this object is held in some place for a long time and the data has changed considerably, so that the lazily fetched data is much different that the data already loaded when the session was alive. This is what you need to be concerned about.
To put it simple you can safely use this setting if your program is not affected by: How stale the data that was already fetched when in session to the data that will be fetched lazily out of session
But if this (your program is exposed to timing issues, when it might work fine one time and fail another time) is a concern, then fetch all the necessary data while in session.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With