-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 
Author Message
 Post subject: Cached POs with a proxy
PostPosted: Wed Mar 10, 2004 10:47 pm 
Regular
Regular

Joined: Tue Nov 11, 2003 7:35 pm
Posts: 63
I seem to be having a problem caching Persistant Objects that have been mapped to use a proxy. Specifically, I am doing a HQL query to return these POs, the first request is successful, but a the second request, if I use the cached query results I get the following exception:

net.sf.hibernate.HibernateException: Could not initialize proxy - the
owning Session was closed
at
net.sf.hibernate.proxy.LazyInitializer.initialize(LazyInitializer.java:47)
at
net.sf.hibernate.proxy.LazyInitializer.initializeWrapExceptions(LazyInitializer.java:60)
at
net.sf.hibernate.proxy.LazyInitializer.getImplementation(LazyInitializer.java:164)
at
net.sf.hibernate.proxy.CGLIBLazyInitializer.intercept(CGLIBLazyInitializer.java:108)
at
org.ifmc.qies.qw.data.po.QwDataGrp$$EnhancerByCGLIB$$14a5c192.getSqncNum()

etc.

Let me know if you need more info, I am in a bit of a rush at the moment. I have a PO named "Orders" which is mapped with proxy="package.name.Orders". Basically I am running a cached query such as this:

select o from Orders where name="somebody"

and I am displaying some info about the orders on my web page by iterating over the resulting List. (I am calling some getter methods on the fields so I know the proxy gets initialized). The first time this is run there is no error. However, if I would press "reload" in my browser (which loads the cached results in a new session) I get the error posted above.

Am I misunderstanding how caching proxied objects is supposed to work? Why would this error occur? Is it perhaps a problem since I am using the query cache?

I am using version 2.1.2.

Thanks in advance,
Daniel


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 11, 2004 1:07 pm 
Regular
Regular

Joined: Tue Nov 11, 2003 7:35 pm
Posts: 63
I found the reason for this error. My session was being closed before the objects got displayed.

The first time after the query was run, the result set came back with objects all initialized already, so even though the session was closed they all displayed correctly. However, in the second request, when the cached query results are used, internally the id set of all the rows are used to fetch those objects already cached in the previous request. At that point the code thinks that the proxied objects are not initialized, so it tries to initialize it, and seeing that the session is closed it throws the exception.

What I dont understand is why the session must be open when using the results of the second query. After all, when the objects were placed in the cache by the first request they were initialized proxies, so why when the second request tries to use them are they not still initialized? Why would those objects lose their "initialized" status?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 17, 2004 12:02 am 
Regular
Regular

Joined: Tue Nov 11, 2003 7:35 pm
Posts: 63
Since I did not get any replies to my question, perhaps I am not being clear. I will now be more specific.

I have code similar to this:

Code:
Session session1 = sessionFactory.openSession() ;
Query query1 = session1.createQuery("from Orders o where o.userId=:userId");
query1.setString("userId", "SOMEONE");
query1.setCacheable(true);
List results1 = query1.list();

// now close the session
session.close();

// even though the session is closed this iteration has no problem,
// since the query returned initialized proxied Order objects
for (int i = 0; i < results1.length(); i++) {
  Order o = (Order)results1.get(i);
  System.out.println("order description = " + o.getDesc());
}

// but the second time does not work:
Session session2 = sessionFactory.openSession() ;
Query query2 = session2.createQuery("from Orders o where o.userId=:userId");
query2.setString("userId", "SOMEONE");
query2.setCacheable(true);

// will return the cached results of the first query
List results2 = query2.list();

// now close the session
session.close();

// this time closing the session IS a problem, and will result in the exception noted above
for (int i = 0; i < results2.length(); i++) {
  Order o = (Order)results2.get(i);
  System.out.println("order description = " + o.getDesc());
}


Note once again that the Order object is mapped to use a proxy, and the Desc field is not part of the PK so the proxy needs to be initialized in order to get the value.

So my question is, if the first query already loads proxied objects that are already initialized and places the already initialized objects into the second-level cache, why when the 2nd query retrieves the cached results do those objects lose the "initialized" status? Why is the first query different than the 2nd, that with the first query it doesn't matter if the session is closed or not but in the second query it does? Is this perhaps a bug?

(In case you are wondering, others on my team want the Hibernate session closed in the servlet before forwarding to the JSP. So I would put the resulting List in the http servlet request object and iterate over the elments in my JSP to display the results. I would hate in my servlets to have to iterate over the result set and call initialize() on every element every time I run a query that the results would be used in this fashion. It seems a bug. )

Thanks,
Daniel


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 17, 2004 2:59 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
This is correct and expected functionality. Entity state is NOT cached in the query cache. (It is not that hard to iterate over query results and call Hibernate.initialize(), by the way.)


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 17, 2004 10:42 am 
Regular
Regular

Joined: Tue Nov 11, 2003 7:35 pm
Posts: 63
Thanks for the reply Gavin.

Isn't this inefficient though? After all the objects were already initialized when they were placed in the cache, so what additional benefit is there when they come back in an uninitialized state when fetching them from the cache subsequentially?

(Also it is not that it is difficult to iterate over the result set and call initialize(), it is just that this would need to be done in almost every servlet we have that uses any sort of cached query results. And it is bug prone in the sense that if one forgets in one place to place this loop that page would have an exception.

It is also a bit of a difficult bug to find, as when the user encounters the page the first time everything appears working fine. It is only the second time the user goes to that page that the exception occurs (such as if they hit the refresh button). It would be much less error prone to have the cached query objects to come back initialized as they were when the query first ran. For what purpose are they pulled from the cache unitialized that this is "expected behavior"?)


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 17, 2004 11:02 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Your suggested strategy could result in loading the entire cache into the session. Ok, thats a bit extreme. But a user found that for a complex object graph, "eager" loading from the cache was a performance bug.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.