-->
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.  [ 5 posts ] 
Author Message
 Post subject: query cache and filters broken?
PostPosted: Fri Apr 22, 2005 11:45 am 
I am using the query cache and filters as the mapping and code below
shows.
Well my problem is that the query cache does not use the filter parameter as part of the key as evident from the toString below. The result is that I get a leakage between different filters.

/Konstantin

PS Everything works fine when the cache is disabled

Hibernate version:3.01

Mapping documents:

<hibernate-mapping>

<class name="MenuElementInfo" table="CMT_MENU_ELEMENTS">

<cache usage="nonstrict-read-write"/>

<id name="id" unsaved-value="-1">
<column name="element_id"/>
<generator class="native">
<param name="sequence">CMT_MENU_ELEMENT_SEQ</param>
</generator>
</id>

<property name="menuText" column="element_txt"/>

<property name="menuLink" column="element_link"/>

<property name="altText"/>

<property name="titleText"/>

<property name="publicName"/>

<property name="edition"/>

<property name="parentId" column="parent_id" type="int" insert="false" update="false"/>


<many-to-one name="parentImpl" column="parent_id" class="se.posten.pse.verktyg.cmt.MenuElementInfo"/>



<list name="children" outer-join="true" lazy="true" cascade="all">
<cache usage="nonstrict-read-write"/>
<key column="parent_id"/>
<index column="order_id"/>

<one-to-many class="se.posten.pse.verktyg.cmt.MenuElementInfo"/>
</list>

<filter name="editionFilter" condition=":editionParam = edition"/>

</class>

<!-- remove when menus are a part of the same schema as the rest of cmt -->
<filter-def name="editionFilter">
<filter-param name="editionParam" type="string"/>
</filter-def>

</hibernate-mapping>



Code between sessionFactory.openSession() and session.close():


session.enableFilter("editionFilter").setParameter("editionParam", Editions.getEdition());
MenuElementInfo menuElementInfo = (MenuElementInfo) sessionIn.createCriteria(MenuElementInfo.class)
.add(Expression.eq("publicName", publicName)).setCacheable(true).uniqueResult();



Full stack trace of any exception that occurs:

Name and version of the database you are using:

The generated SQL (show_sql=true):

SQL against db:
select this_.element_id as element1_1_, this_.element_txt as element2_0_1_, this_.element_link as element3_0_1_, this_.altText as altText0_1_, this_.titleText as titleText0_1_, this_.publicName as publicName0_1_, this_.edition as edition0_1_, this_.parent_id as parent8_0_1_, children2_.parent_id as parent8___, children2_.element_id as element1___, children2_.order_id as order9___, children2_.element_id as element1_0_, children2_.element_txt as element2_0_0_, children2_.element_link as element3_0_0_, children2_.altText as altText0_0_, children2_.titleText as titleText0_0_, children2_.publicName as publicName0_0_, children2_.edition as edition0_0_, children2_.parent_id as parent8_0_0_ from CMT_MENU_ELEMENTS this_ left outer join CMT_MENU_ELEMENTS children2_ on this_.element_id=children2_.parent_id where ? = this_.edition and this_.publicName=?

SQL query cache key (toString()):
sql: select this_.element_id as element1_1_, this_.element_txt as element2_0_1_, this_.element_link as element3_0_1_, this_.altText as altText0_1_, this_.titleText as titleText0_1_, this_.publicName as publicName0_1_, this_.edition as edition0_1_, this_.parent_id as parent8_0_1_, children2_.parent_id as parent8___, children2_.element_id as element1___, children2_.order_id as order9___, children2_.element_id as element1_0_, children2_.element_txt as element2_0_0_, children2_.element_link as element3_0_0_, children2_.altText as altText0_0_, children2_.titleText as titleText0_0_, children2_.publicName as publicName0_0_, children2_.edition as edition0_0_, children2_.parent_id as parent8_0_0_ from CMT_MENU_ELEMENTS this_ left outer join CMT_MENU_ELEMENTS children2_ on this_.element_id=children2_.parent_id where :editionFilter.editionParam = this_.edition and this_.publicName=?; parameters: Svenska,





Debug level Hibernate log excerpt:


Top
  
 
 Post subject:
PostPosted: Mon Apr 25, 2005 5:59 pm 
I have created a TestCase that reveals the bug...
If anybody cares :-)


Code:
/*
* Created on 2005-apr-25
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
package org.hibernate.test.filter;

import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.stat.QueryStatistics;
import org.hibernate.test.TestCase;

/**
*TestCase that shows that secondlevelcache and filters dont work together.
*
*The parameter to the filter is not passed on to the cache so we get false hits in it.
*
*/
public class FilterCacheBugTest extends TestCase {

   /**
    * @param x
    */
   public FilterCacheBugTest(String x) {
      super(x);
      // TODO Auto-generated constructor stub
   }

      
   public void testFilterCacheBug(){
      Session s = openSession();
      
      QueryStatistics qs = s.getSessionFactory()
      .getStatistics()
      .getQueryStatistics("from org.hibernate.test.filter.Order");
      
      
      s= openSession();
      s.enableFilter("region").setParameter("region","ABC");
      s.createQuery("from Order").setCacheable(true).list();
      assertEquals(0,qs.getCacheHitCount());
      
      
      s.enableFilter("region").setParameter("region","ABC");
      s.createQuery("from Order").setCacheable(true).list();
      assertEquals(1,qs.getCacheHitCount());
      
      
      s.enableFilter("region").setParameter("region","DEF");
      s.createQuery("from Order").setCacheable(true).list();
//      Setting filter to another value should make query run again but it fails with another cachehit (value will be 2)
      assertEquals(1,qs.getCacheHitCount());
      
      
      s.close();
   }
   
   protected void configure(Configuration cfg) {
      super.configure( cfg );
      cfg.setProperty( Environment.USE_QUERY_CACHE, "true" );
      cfg.setProperty( Environment.CACHE_REGION_PREFIX, "foo" );
      cfg.setProperty( Environment.USE_SECOND_LEVEL_CACHE, "true" );
      cfg.setProperty( Environment.GENERATE_STATISTICS, "true" );
   }
   
   /* (non-Javadoc)
    * @see org.hibernate.test.TestCase#getMappings()
    */
   protected String[] getMappings() {
      return new String[] {
            "filter/defs.hbm.xml",
            "filter/LineItem.hbm.xml",
            "filter/Order.hbm.xml",
            "filter/Product.hbm.xml",
            "filter/Salesperson.hbm.xml",
            "filter/Department.hbm.xml"
         };
   }


}


Top
  
 
 Post subject:
PostPosted: Mon Apr 25, 2005 9:45 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Caching for filtered queries is not currently implemented. There is an existing TODO in JIRA for this.

(Likewise, there is no caching for filtered collections.)


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 25, 2005 11:27 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
I implemented this in CVS.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 26, 2005 3:30 am 
Nice! I can use my testcase to see if you have done your job right :-)


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