I have run into LazyInitializationException and then I ran into the following paragraph from the official doc. Unfortunately, it makes absolutely no sense to me. Please help.
(The code block above the paragraph in the doc.)
@GET
@Timed
@UnitOfWork
public Person findPerson(@PathParam("id") LongParam id) {
return dao.findById(id.get());
}
Important
The Hibernate session is closed before your resource method’s return value (e.g., the Person from the database), which means your resource method (or DAO) is responsible for initializing all lazily-loaded collections, etc., before returning. Otherwise, you’ll get a LazyInitializationException thrown in your template (or null values produced by Jackson).
First The Hibernate session is closed before your resource method’s return value. How is this possible? This would have been possible had there been a try-finally block around my resource's return statement, but that is not the case here.
My resource should have been invoked by another method, which I am guessing would open the Hibernate session before my resource method is invoked and would then close the session after my resource method returns. How can it close it before my method returns. I don't get it.
The most important part - which means your resource method (or DAO) is responsible for initializing all lazily-loaded collections, etc., before returning. I have no Hibernate experience. I am using it for the first time now. How do I initialize, or rather what is exactly is meant by "initialize" in context of Hibernate? A code example will help a lot.
PS: This question might look odd, and someone at a cursory glance might even suggest to move it to "English Language and Usage", but please read it carefully. This is a technical question, not paragraph dissection.
Edit: Added the code block from the doc else it won't make sense anyone. Also I removed one paragraph from my question, which became clear to me, immediately after posting the question.
First The Hibernate session is closed before your resource method’s return value. How is this possible? This would have been possible had there been a try-finally block around my resource's return statement, but that is not the case here.
I know nothing about Dropwizard. So let's see the source (I change it a bit).
From UnitOfWorkAwareProxyFactory
class UnitOfWorkAwareProxyFactory {
public <T> T create(Class<T> clazz) {
final ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(clazz);
final Proxy proxy = (Proxy) factory.createClass().newInstance();
proxy.setHandler(new MethodHandler() {
@Override
public Object invoke(Object self, Method overridden,
Method proceed, Object[] args) {
final UnitOfWork unitOfWork = overridden.getAnnotation(UnitOfWork.class);
final UnitOfWorkAspect unitOfWorkAspect = new UnitOfWorkAspect(sessionFactories);
try {
unitOfWorkAspect.beforeStart(unitOfWork);
Object result = proceed.invoke(self, args);
unitOfWorkAspect.afterEnd();
return result;
} catch (Exception e) {
unitOfWorkAspect.onError();
throw e;
}
}
});
return (T) proxy;
}
}
if you have a class
class PersonDao {
@UnitOfWork
public Person findPerson(LongParam id) {
return dao.findById(id.get());
}
}
You can do something like this
UnitOfWorkAwareProxyFactory factory = new UnitOfWorkAwareProxyFactory();
PersonDao proxy = factory.create(PersonDao.class);
when you do
Person person = proxy.findPerson(1L);
that line becomes
unitOfWorkAspect.beforeStart(unitOfWork);
Object result = findPerson.invoke(proxy, 1L);
unitOfWorkAspect.afterEnd();
return result;
Methods unitOfWorkAspect.beforeStart(unitOfWork) and unitOfWorkAspect.afterEnd() from the source UnitOfWorkAspect
class UnitOfWorkAspect {
public void beforeStart(UnitOfWork unitOfWork) {
session = sessionFactory.openSession();
configureSession();
beginTransaction();
}
public void afterEnd() {
try {
commitTransaction();
} catch (Exception e) {
rollbackTransaction();
throw e;
} finally {
session.close();
}
}
}
The most important part - which means your resource method (or DAO) is responsible for initializing all lazily-loaded collections, etc., before returning. I have no Hibernate experience. I am using it for the first time now. How do I initialize, or rather what is exactly is meant by "initialize" in context of Hibernate?
Initialize in this context means the collection data should be loaded from a database. Some methods of an initialization
1.Use an eager loading, for an example
class User {
@ManyToMany(fetch = FetchType.EAGER)
private List<Role> roles;
}
Hibernate will load roles via joins or subselects, when you get a User entity.
Hibernate.initialize(user.getRoles())join fetch in HQL — from User user left join fetch user.rolesCriteria with setFetchMode()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