-->
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: CollectionCacheEntry unsafe with QueryCache?
PostPosted: Thu Sep 06, 2007 1:13 pm 
Newbie

Joined: Thu Aug 16, 2007 1:34 pm
Posts: 3
Hi,

I have two cached queries that return a collection of the same type of object.

The first query returns a subset of an association, and then the second query returns a different subset of the same association.

The problem is that there is only one CollectionCacheEntry in the cache, and it gets overridden by the second query.

    * Run a cached query to return all sales for a given user that have id > 10.
    * Hibernate checks to see if the query is in the StandardQueryCache.
    * It is not, so the query runs and returns a result set.
    * The result set (the ids of the sales > 10) is saved as a CollectionCacheEntry in the cache. The key being the User.

Code:
       Transaction tx = session.beginTransaction();
       tx = session.beginTransaction();
       
        String hql = "FROM SalesUser su " +
           "LEFT JOIN FETCH su.sales s"     +
           "          WHERE su.id = :id " +
              "          AND   s.id > 10 ";
        Query q = session.createQuery(hql);
        q.setInteger("id", 286);
        q.setReadOnly(true);
        q.setCacheable(true);
        Set<SalesUser> ts = new HashSet<SalesUser>();
        for (Object suTemp: q.list()) {
           ts.add((SalesUser)suTemp);
        }
        for (SalesUser su: ts) {
           for (Sales s: su.getSales()) {
              System.out.println("Found sales:" + s.getId());
           }
        }
        tx.commit();


KEY: my.package.SalesUser.sales#286.my.package.SalesUser.sales
CONTENT: CollectionCacheEntry[10,11,12,13,20,21,22,23]


    * Run another cached query to return all sales for the same user that have id > 20.
    * Hibernate checks to see if the query is in the StandardQueryCache.
    * It is not, so the query runs and returns a result set.
    * The result set (the ids of the sales > 20) is saved as a CollectionCacheEntry in the cache. The key being the same User.
    * This replaces the CollectionCacheEntry returned from the first query.

Code:

   Transaction tx = session.beginTransaction();
       tx = session.beginTransaction();
       
        String hql = "FROM SalesUser su " +
           "LEFT JOIN FETCH su.sales s"     +
           "          WHERE su.id = :id " +
              "          AND   s.id > 20 ";
        Query q = session.createQuery(hql);
        q.setInteger("id", 286);
        q.setReadOnly(true);
        q.setCacheable(true);
        Set<SalesUser> ts = new HashSet<SalesUser>();
        for (Object suTemp: q.list()) {
           ts.add((SalesUser)suTemp);
        }
        for (SalesUser su: ts) {
           for (Sales s: su.getSales()) {
              System.out.println("Found sales:" + s.getId());
           }
        }
        tx.commit();


KEY: my.package.SalesUser.sales#286.my.package.SalesUser.sales
CONTENT: CollectionCacheEntry[20,21,22,23]


    * Run the first cached query to return all sales for a given user that have id > 10.
    * Hibernate checks to see if the query is in the StandardQueryCache.
    * It is, so it uses the CollectionCacheEntry for the User object.
    * The result set (the ids of the sales > 20) is returned for a query that is supposed to return the sales with ids > 10!

Code:
       Transaction tx = session.beginTransaction();
       tx = session.beginTransaction();
       
        String hql = "FROM SalesUser su " +
           "LEFT JOIN FETCH su.sales s"     +
           "          WHERE su.id = :id " +
              "          AND   s.id > 10 ";
        Query q = session.createQuery(hql);
        q.setInteger("id", 286);
        q.setReadOnly(true);
        q.setCacheable(true);
        Set<SalesUser> ts = new HashSet<SalesUser>();
        for (Object suTemp: q.list()) {
           ts.add((SalesUser)suTemp);
        }
        for (SalesUser su: ts) {
           for (Sales s: su.getSales()) {
              System.out.println("Found sales:" + s.getId());
           }
        }
        tx.commit();


KEY: my.package.SalesUser.sales#286.my.package.SalesUser.sales
CONTENT: CollectionCacheEntry[20,21,22,23]


Error: The result set should be [10,11,12,13,20,21,22,23]

Sales User Object Mapping
Code:
<hibernate-mapping package="my.package">
    <class name="SalesUser" table="sales_user">
        <id name="id" column="userId" type="long">
            <generator class="native"/>
        </id>
        <set name="sales" inverse="true">
            <cache usage="nonstrict-read-write"/>
            <key column="salesPersonId"/>
            <one-to-many class="Sales"/>
       </set>

    </class>
</hibernate-mapping>


Sales Object Mapping
Code:
<hibernate-mapping package="my.package">
    <class name="Sales" table="sales">
        <id name="id" column="salesId" type="long">
            <generator class="native"/>
        </id>
    </class>
</hibernate-mapping>



Is there a way to ensure that the key used for the CollectionCacheEntry is uniqely associated with a parameterized cached query so that is is only returned when that specific query is executed?

Thanks,

-Erik


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 06, 2007 6:34 pm 
Expert
Expert

Joined: Tue Nov 23, 2004 7:00 pm
Posts: 570
Location: mostly Frankfurt Germany
I have nether seen this before. Could you post your configuration?

_________________
Best Regards
Sebastian
---
Training for Hibernate and Java Persistence
Tutorials for Hibernate, Spring, EJB, JSF...
eBook: Hibernate 3 - DeveloperGuide
Paper book: Hibernate 3 - Das Praxisbuch
http://www.laliluna.de


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 06, 2007 6:59 pm 
Newbie

Joined: Thu Aug 16, 2007 1:34 pm
Posts: 3
Here is the hibernate.cgf.xml:

Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
        <session-factory>
       
            <property name="connection.username">root</property>
          <property name="connection.password"></property>
          <property name="connection.url">jdbc:mysql://localhost:3306/mydb</property>
          
          <property name="connection.driver_class">
              com.mysql.jdbc.Driver
          </property>
          <property name="dialect">
              org.hibernate.dialect.MySQLDialect
          </property>
   
            <property name="max_fetch_depth">3</property>
            <property name="show_sql">true</property>
            <property name="cache.provider_class">com.opensymphony.oscache.hibernate.OSCacheProvider</property>
            <property name="com.opensymphony.oscache.configurationResourceName">my/package/oscache.properties</property>
            <property name="cache.use_query_cache">true</property>

          <!-- configuration pool via c3p0-->
          <property name="c3p0.min_size">10</property>
          <property name="c3p0.max_size">100</property> 
          <property name="c3p0.acquireIncrement">1</property>
          <property name="c3p0.acquire_increment">1</property>
          <property name="c3p0.idleTestPeriod">100</property> <!-- seconds -->
          <property name="c3p0.maxStatements">0</property>
          <property name="c3p0.checkoutTimeout">20000</property>
          <property name="c3p0.timeout">100</property> <!-- seconds -->

            <mapping resource="my/package/Sales.hbm.xml" />
            <mapping resource="my/package/SalesUser.hbm.xml" />

            <class-cache class="com.meltwater.common.data.model.Sales" usage="nonstrict-read-write" />
            <class-cache class="com.meltwater.common.data.model.SalesUser" usage="nonstrict-read-write" />
        </session-factory>
</hibernate-configuration>


And the oscache.properties file:

Code:
# CACHE LISTENERS
#
# These hook OSCache events and perform various actions such as logging
# cache hits and misses, or broadcasting to other cache instances across a cluster.
# See the documentation for further information.
#
# cache.event.listeners=com.opensymphony.oscache.plugins.clustersupport.JMSBroadcastingListener,  \
#                       com.opensymphony.oscache.extra.CacheEntryEventListenerImpl,               \
#                       com.opensymphony.oscache.extra.CacheMapAccessEventListenerImpl,           \
#                       com.opensymphony.oscache.extra.ScopeEventListenerImpl,                    \
#                       com.opensymphony.oscache.extra.StatisticListenerImpl

cache.event.listeners=com.opensymphony.oscache.plugins.clustersupport.JavaGroupsBroadcastingListener

# CACHE SIZE
#
# Default cache size in number of items. If a size is specified but not
# an algorithm, the cache algorithm used will be LRUCache.
#
cache.capacity=100000

# JAVAGROUPS CLUSTER PROPERTIES
#
# Configuration properites for the JavaGroups clustering. Only one of these
# should be specified. Default values (as shown below) will be used if niether
# property is set. See the clustering documentation and the JavaGroups project
# (www.javagroups.com) for more information on these settings.
#
cache.cluster.multicast.ip=231.12.21.132


Top
 Profile  
 
 Post subject:
PostPosted: Fri Sep 07, 2007 3:04 am 
Expert
Expert

Joined: Tue Nov 23, 2004 7:00 pm
Posts: 570
Location: mostly Frankfurt Germany
It seems that you haven't defined the cache areas for the query cache. I am not using oscache, so I cannot give you a feedback on the configuration.

_________________
Best Regards
Sebastian
---
Training for Hibernate and Java Persistence
Tutorials for Hibernate, Spring, EJB, JSF...
eBook: Hibernate 3 - DeveloperGuide
Paper book: Hibernate 3 - Das Praxisbuch
http://www.laliluna.de


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.