Reputation: 20845
First I need to acknowledge the fact that I'm new to EJB, JPA and Spring, so many of the things I believe as true could be wrong.
I'm building an EJB application where there's an stateless session bean used to retrieve many JPA (Hibernate) entities. The problem, which I believe is a widespread problem, is that I cannot traverse the relationships of those entities when the stateless returns any instance. I get the dreaded LazyInitializationException. In many cases I found that using eager fetching I could avoid the exception, but this felt more like a workaround than a real fix. After lots of googling, I found that (since I'm using spring) probably the most intrusive way to accomplish this was using OpenSessionInViewInterceptor.
Reading this looks like it's easy to use, but I can't map the files mentioned in the article. One possible explanation is that I'm using Spring 3, so the names for the files might have changed. I do have a spring3app-servlet.xml where beans are being declared. I also have a web.xml where filters are set (this file I believe that was used with spring 2.0, but it still works with 3.0).
Further searching made me realize that the filenames weren't my only concern, since I don't have any SessionFactory bean, which I believe it's necessary for this to work. This lead me to search info about the SessionFactory bean.
That search made me realize that I probably need .hbm.xml files. I'm not sure if those files are really needed, or if they where a requisite for legacy hibernate-spring versions.
tl;dr: I want an OpenSessionInViewInterceptor. Do I need a SessionFactory Bean? Do I need .hbm.xml files? Where can I find all the information to set this up?
Edit:
Maybe the solution is using OpenSessionInViewFilter. I'm trying to use it but it still fails with the same exception. I'm reading this in search of a fix.
Upvotes: 2
Views: 3174
Reputation: 8512
First, if you're going for an all out JPA solution, you should use OpenEntityManagerInViewFilter. Which does something similar to OpenSessionInViewInterceptor, but for JPA
As for the session bean, you will always get a LazyInitializationException since the object is loaded in a different session. Lazy fields are only accessible in the current http request. If you access the field in another http request you will get a LazyInitializationException.
(by the way hibernate define a http request as "Session". But a Spring session covers multiple http request. Yes this is confusing).
What you can do to avoid the LazyInitializationException is:
Reload the session bean. For example:
MyObject objectFromDb = objectDAO.find(objectFromSession.getId());
Or initialize the field when you set the field in a session bean:
Hibernate.initialize(field);
(don't forget to recurse over all children fields)
Ok, since this is the same session, you do need a OpenEntityManagerInViewFilter/OpenSessionInViewInterceptor, which will create an Hibernate session for each Http request. So put an entry in your web.xml:
<filter>
<filter-name>JpaFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>JpaFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
The OpenEntityManagerInViewFilter is similar. Also make sure that your "entityManagerFactory" bean is injected in your filter.
Upvotes: 4