Hibernate version: 
3.2.6 

We ran into an issue where detached query causes stale query cache
entries. Our example is to retrieve a list of our favorite dogs. We use
a separate table called favorite_animal to store our favorite animals,
including dogs. 

For example, our main query is the following, 

from Dog 

And we use a detached query to select our favorite Dog, 
select fa.animal_id from favoriate_animal fa where fa.user_id = :user_id


The combined SQL looks like the following, 
from Dog dog where dog.id in (select fa.animal_id from favoriate_animal
fa where fa.user_id = :user_id) 

There is our problem. We execute the above query once and get a list of
dogs back. We then remove one dog from our favorite list and then run
the above query again. We are expected to see one less dog in our result
but we got the same list as before! 

It turns out that the query cache entry was not invalidated when we
removed one dog from the favorite list. I dug a little and it seems like
the query spaces used to look up invalidated entity names are only built
from associated criteria, but not from detached query or detached query
based criterion. 

In our example, the query spaces will only contain [DOG] entity. 

I had made some changes to CriteriaQueryTranslator to include additional
query spaces from detached queries in getQuerySpaces method in
CriteriaQueryTranslator but want to make sure that I am on the right
track. 

After my fix, the query spaces will contain [DOG,FAVORITE_ANIMAL]. 



I am attaching a patch as well.

Thanks for your feedback and comments. 

-- Lei

Index: 
C:/dev_home/Hibernate/Hibernate3.2.6/src/org/hibernate/criterion/SubqueryExpression.java
===================================================================
--- 
C:/dev_home/Hibernate/Hibernate3.2.6/src/org/hibernate/criterion/SubqueryExpression.java
    (revision 53)
+++ 
C:/dev_home/Hibernate/Hibernate3.2.6/src/org/hibernate/criterion/SubqueryExpression.java
    (working copy)
@@ -38,7 +38,11 @@
        }
        
        protected abstract String toLeftSqlString(Criteria criteria, 
CriteriaQuery outerQuery);
-
+       
+    public CriteriaImpl getDetachedCriteriaImpl()
+    {
+        return criteriaImpl;
+    }
        public String toSqlString(Criteria criteria, CriteriaQuery 
criteriaQuery)
        throws HibernateException {
 
Index: 
C:/dev_home/Hibernate/Hibernate3.2.6/src/org/hibernate/loader/criteria/CriteriaQueryTranslator.java
===================================================================
--- 
C:/dev_home/Hibernate/Hibernate3.2.6/src/org/hibernate/loader/criteria/CriteriaQueryTranslator.java
 (revision 53)
+++ 
C:/dev_home/Hibernate/Hibernate3.2.6/src/org/hibernate/loader/criteria/CriteriaQueryTranslator.java
 (working copy)
@@ -20,7 +20,9 @@
 import org.hibernate.QueryException;
 import org.hibernate.hql.ast.util.SessionFactoryHelper;
 import org.hibernate.criterion.CriteriaQuery;
+import org.hibernate.criterion.Criterion;
 import org.hibernate.criterion.Projection;
+import org.hibernate.criterion.SubqueryExpression;
 import org.hibernate.engine.QueryParameters;
 import org.hibernate.engine.RowSelection;
 import org.hibernate.engine.SessionFactoryImplementor;
@@ -114,6 +116,22 @@
                        String entityName = ( String ) iter.next();
                        result.addAll( Arrays.asList( 
getFactory().getEntityPersister( entityName ).getQuerySpaces() ) );
                }
+        
+        iter = rootCriteria.iterateExpressionEntries();
+        
+        while (iter.hasNext())
+        {
+            CriteriaImpl.CriterionEntry entry = (CriteriaImpl.CriterionEntry) 
iter.next();
+            
+            Criterion criterion = entry.getCriterion();
+            
+            if (criterion instanceof SubqueryExpression)
+            {
+                SubqueryExpression subqueryExpression = (SubqueryExpression) 
criterion;
+                
+                result.addAll(Arrays.asList(getFactory().getEntityPersister( 
subqueryExpression.getDetachedCriteriaImpl().getEntityOrClassName() 
).getQuerySpaces()));
+            }
+        }
                return result;
        }
 
_______________________________________________
hibernate-dev mailing list
hibernate-dev@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/hibernate-dev

Reply via email to