Another way to avoid LazyInitializationException is to disable lazy initialization feature of hibernate for your entity classes by using lazy="false" or disable it completely for your application by using default-lazy="false".
Hibernate implements lazy initializing proxies for persistent objects using runtime bytecode enhancement (via the excellent CGLIB library). By default, Hibernate3 generates proxies (at startup) for all persistent classes and uses them to enable lazy fetching of many-to-one and one-to-one associations.
Hibernate now can "lazy-load" the children, which means that it does not actually load all the children when loading the parent. Instead, it loads them when requested to do so. You can either request this explicitly or, and this is far more common, hibernate will load them automatically when you try to access a child.
The Session interface is the main tool used to communicate with Hibernate. It provides an API enabling us to create, read, update, and delete persistent objects. The session has a simple lifecycle. We open it, perform some operations, and then close it.
If you using Spring mark the class as @Transactional, then Spring will handle session management.
@Transactional
public class MyClass {
...
}
By using @Transactional
, many important aspects such as transaction propagation are handled automatically. In this case if another transactional method is called the method will have the option of joining the ongoing transaction avoiding the "no session" exception.
WARNING If you do use @Transactional
, please be aware of the resulting behavior. See this article for common pitfalls. For example, updates to entities are persisted even if you don't explicitly call save
You can try to set
<property name="hibernate.enable_lazy_load_no_trans">true</property>
in hibernate.cfg.xml or persistence.xml
The problem to keep in mind with this property are well explained here
What is wrong here is that your session management configuration is set to close session when you commit transaction. Check if you have something like:
<property name="current_session_context_class">thread</property>
in your configuration.
In order to overcome this problem you could change the configuration of session factory or open another session and only than ask for those lazy loaded objects. But what I would suggest here is to initialize this lazy collection in getModelByModelGroup itself and call:
Hibernate.initialize(subProcessModel.getElement());
when you are still in active session.
And one last thing. A friendly advice. You have something like this in your method:
for (Model m : modelList) {
if (m.getModelType().getId() == 3) {
model = m;
break;
}
}
Please insted of this code just filter those models with type id equal to 3 in the query statement just couple of lines above.
Some more reading:
session factory configuration
problem with closed session
The best way to handle the LazyInitializationException
is to use the JOIN FETCH
directive:
Query query = session.createQuery("""
select m
from Model m
join fetch m.modelType
where modelGroup.id = :modelGroupId
"""
);
Anyway, DO NOT use the following Anti-Patterns as suggested by some of the answers:
hibernate.enable_lazy_load_no_trans
Sometimes, a DTO projection is a better choice than fetching entities, and this way, you won't get any LazyInitializationException
.
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