I am trying to implement a Hibernate persistence level in a Java application and I am having problems with it. I encounter a lack of proxy error every time I try to access a simple one-way association. I did not implement Hibernate completely correctly - I use the session control flow method that they suggest that you do not use it for production. However, they use it in their textbooks. I'm still trying to get the basics to work, so I decided that after the tutorials everything would be okay. However, I cannot get a simple association to work. I have a class that looks something like this:
public class Foo { private Long id; private String name; private Bar bar;
The Foo Bar class is implemented as a simple one-way communication. This is in the .hbm.xml file, for example:
<many-to-one name="bar" column="bar_id" not-null="true" />
I create Foo in a static method inside Foo like this:
public static List getAllFoo() { Session session = HibernateUtil.getSessionFactory().getCurrentSession(); Transaction t = session.beginTransaction(); List foos = session.createCriteria(Foo.class).list(); t.commit(); return foos; }
The hibernate instance is configured to use connection pool 1 and uses the streaming processing method to handle the session as follows:
<property name="connection.pool_size">1</property> <property name="current_session_context_class">thread</property>
I encounter an exception every time I try to access the association using the getBarName() function on one of the created objects. This is a proxy error, it looks like this:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:132) at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:174) at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190) at Bar_$$_javassist_7.getName(Bar_$$_javassist_7.java) at Foo.getBarName(Bar.java:126)
So, to make a long story short, this is where I started and the mistake I first encountered. Since then, I spent the last few days reading Hibernate documents and posts here to try and figure out how to do this.
What I found out, I think, is that Hibernate objects should be connected to the session. Namely, the Session they are created. When I create my objects, in getAllFoo() is the session to which these objects relate. In this session, the Bar proxy exists and makes sense. However, when I call t.commit() - because I use the Thread method to handle the session - I end this session. The result of this is that when I switch to calling bar.getName() later, bar will now become a proxy orphan. This is a proxy server whose session is closed.
I found two possible solutions:
1) do not close the initial session. Leave it open without typing t.commit() in getAllFoo() .
It worked - but I don't think I can use it. I am going to download thousands of these objects at once. They should remain open for a long period of time while the user thinks about time - but I need to be able to freely access associations. And in the future, there may be problems with concurrency database locks.
2) reconnect the object to the new session before calling the association.
This did not work. Perhaps I did it wrong - the documentation I found is not clear. I tried to start a new session and call session.load(this, this.id) before I turned to the association. Like this:
public Bar getBar() { Bar tmp = null; Session session = HibernateUtil.getSessionFactory().getCurrentSession(); Transaction t = session.beginTransaction(); session.load(this, this.id); tmp = bar; t.commit(); return tmp; }
Then I modified getBarName() to call getBar() instead of accessing the bar. As a result, a new error appeared:
org.hibernate.PersistentObjectException: attempted to load into an instance that was already associated with the session: [Foo
I think that even after several days of reading textbooks, messages, and hibernation documentation, I still cannot wrap my head around this structure. Therefore, I ask StackOverflow to shed light on this.
First, if you can understand what is going on in the code that I currently have? Is the session open or closed? Why does he have a proxy error in the first method, but claim that the session is still open and the object is still bound to the second?
Secondly, what is the correct way to handle sessions - how can I make this work? . I think I want to use a session for each request - this is apparently the most popular and applicable to my situation. But then, how is this actually implemented with associations and lazy loading?
Yes, I know that I should not use the thread method, but I have a whole other batch of questions related to JTA vs Thread vs Managed, and this question is already too long.