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 2Now, 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).