-->
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.  [ 4 posts ] 
Author Message
 Post subject: QueryCache not working properly with Entities as parameters
PostPosted: Fri Sep 12, 2008 7:00 am 
Proxool Developer
Proxool Developer

Joined: Tue Aug 26, 2003 10:42 am
Posts: 373
Location: Belgium
Hibernate version: 3.3.1.GA (not tested with earlier versions)

I just faced some strange behavior in the way the second level cache works with queries. In short: it seems the QueryCache is not working properly with queries using persistent entities as named parameter.


Suppose a persistent Entity named Employee whose identifier property is uid.
Suppose you configured Hibernate such that this entity is cached.

Scenario 1

Execute the following query (not very useful I admit, but it illustrates the case):

Code:
Query query = getSession().createQuery("from Employee where employee=:employee");
query.setParameter("employee", myEmployeeInstance);
query.setCacheable(true);
return query.uniqueResult();


If you execute this query twice in the same session, results will be returned from the query cache the second time - which is ok.

If you execute this query two times in two different sessions, then you will issue a cache mis all the time - although results have been properly stored in the cache the first time (as per the log output and the outcome of the first test above).


Scenario 2

Now, slightly change the query as follows:

Code:
Query query = getSession().createQuery("from Employee where employee.uid=:employeeUid");
query.setParameter("employeeUid", myEmployeeInstance.getUid());
query.setCacheable(true);
return query.uniqueResult();


The employee instance if not given as parameter to the query anymore, the instance identifier is used. This should clearly lead to the same SQL query as the first scenario.

This time everything works ok - query results are returned from the cache when executed across different sessions (which is what I (wrongly?) expected).


Conclusion

It looks like the QueryKey used internally by Hibernate to store results in the query cache constructs a hashCode value made of (amongst other) the hashCode of the named parameters.

In the first example, if you load the Employee instances from two different sessions will lead to different hashCodes - hence the cache miss.
If you execute the query twice in the same session, you will be using twice the same Employee instance - hence the cache hit.
If you are now using the identifier (provided - as in my case - it is a Java primitive as a Long or any other class with compatible hashCode and equals methods), then the query results will be properly looked up from the cache...


Hence my question

- does someone experience the same behavior ?
- I may be wrong, but it seems to me that Hibernate behave differently in previous versions and intelligently used the hashCode of the entity identifier instead of the hashCode of the entity itself... (this was probably delegated to the internal ManyToOneType implementation).


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 15, 2008 5:01 am 
Proxool Developer
Proxool Developer

Joined: Tue Aug 26, 2003 10:42 am
Posts: 373
Location: Belgium
Nobody experienced the same behavior?
Nobody has any comment on this?

_________________
If you found my post helpful, please rate it! Thanks


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 19, 2009 10:00 am 
Beginner
Beginner

Joined: Fri May 12, 2006 9:58 am
Posts: 32
hello

I got there as well.
It's because Employee does not implement hashcode and equals using a business key.

Let me know if this solves your problem.

Ioannis Cherouvim


Top
 Profile  
 
 Post subject: hashCode/equals?
PostPosted: Thu Apr 09, 2009 2:07 pm 
Newbie

Joined: Thu Apr 09, 2009 2:00 pm
Posts: 1
What happens if you do this instead?
Code:
Query query = getSession().createQuery("from Employee where employee.uid=:employeeUid");
query.setParameter("employeeUid", session.getIdentifier(myEmployeeInstance));
query.setCacheable(true);
return query.uniqueResult();

I bet it's "broke", just like in the first case.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 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.