-->
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.  [ 3 posts ] 
Author Message
 Post subject: Problem when using second level cache and composite id's
PostPosted: Wed Aug 02, 2006 5:11 am 
Newbie

Joined: Wed Aug 02, 2006 4:56 am
Posts: 1
Hi. Can anyone tell me what is wrong with this setup. We've had lots of problems in our application when trying to cache components with composite id's into the second level cache (ehcache or HashTableCache). I've extracted an example set-up below, which describes the problem.

There's two tables with primary keys that consist of two integer fields. They are in no way associated with each other, but they keys can collapse (that is, keys in both table can have same values, pretty normal situation). After loading and cacheing the values from the first table, Hibernate tries to put the values of second table into the cache. This fails with ClassCastException.

Information:

Hibernate version:
3.1

Mapping documents:
Code:
<hibernate-mapping>   
    <class name="oo.pojo.TableA" table="TableA">
        <composite-id name="id" class="oo.pojo.TableAId">   
           <key-property name="A" type="integer">
               <meta attribute="use-in-equals">true</meta>
                <column name="A" />
            </key-property>
            <key-property name="B" type="integer">
               <meta attribute="use-in-equals">true</meta>
                <column name="B" />
            </key-property>
      </composite-id>   
    </class>
   
    <class name="oo.pojo.TableB" table="TableB">
        <composite-id name="id" class="oo.pojo.TableBId">   
           <key-property name="C" type="integer">
               <meta attribute="use-in-equals">true</meta>
                <column name="C" />
            </key-property>
            <key-property name="D" type="integer">
               <meta attribute="use-in-equals">true</meta>
                <column name="D" />
            </key-property>
      </composite-id>   
    </class>
</hibernate-mapping>

<hibernate-configuration>
    <session-factory>
        ...
        <property name="hibernate.show_sql">true</property>
       <property name="hibernate.generate_statistics">true</property>
      <property name="hibernate.cache.use_structured_entries">true</property>
      <property name="hibernate.cache.use_query_cache">true</property>
      <property name="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property>
      
      <mapping resource="oo/mapping/test3.hbm.xml"/>
      
      <class-cache class="oo.pojo.TableA" region="read-write" usage="read-write"/>            
      <class-cache class="oo.pojo.TableB" region="read-write" usage="read-write"/>      
   </session-factory>
</hibernate-configuration>


The component classes are generated from the mapping file with Hibernate tools.

Code between sessionFactory.openSession() and session.close():
Code:
Criteria bCriteria = session.createCriteria(TableB.class);
List<TableB> bList = bCriteria.list();

for (TableB b : bList) {
    System.out.println(b.getId());
}
         
Criteria aCriteria = session.createCriteria(TableA.class);
List<TableA> aList = aCriteria.list();
         
for (TableA a : aList) {
    System.out.println(a.getId());
}


Full stack trace of any exception that occurs:
Code:
org.hibernate.PropertyAccessException: IllegalArgumentException occurred calling getter of oo.pojo.TableBId.C
   at org.hibernate.property.BasicPropertyAccessor$BasicGetter.get(BasicPropertyAccessor.java:171)
   at org.hibernate.tuple.AbstractComponentTuplizer.getPropertyValue(AbstractComponentTuplizer.java:121)
   at org.hibernate.tuple.AbstractComponentTuplizer.getPropertyValues(AbstractComponentTuplizer.java:133)
   at org.hibernate.tuple.PojoComponentTuplizer.getPropertyValues(PojoComponentTuplizer.java:88)
   at org.hibernate.type.ComponentType.getPropertyValues(ComponentType.java:307)
   at org.hibernate.type.ComponentType.isEqual(ComponentType.java:111)
   at org.hibernate.cache.CacheKey.equals(CacheKey.java:51)
   at java.util.Hashtable.get(Hashtable.java:339)
   at org.hibernate.cache.HashtableCache.get(HashtableCache.java:31)
   at org.hibernate.cache.ReadWriteCache.put(ReadWriteCache.java:153)
   at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:153)
   at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:842)
   at org.hibernate.loader.Loader.doQuery(Loader.java:717)
   at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:224)
   at org.hibernate.loader.Loader.doList(Loader.java:2145)
   at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2029)
   at org.hibernate.loader.Loader.list(Loader.java:2024)
   at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:94)
   at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1552)
   at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:283)
   at oo.TestCase.main(TestCase.java:37)
Caused by: java.lang.IllegalArgumentException: java.lang.ClassCastException@b2fb1e
   at sun.reflect.GeneratedMethodAccessor3.invoke(Unknown Source)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
   at java.lang.reflect.Method.invoke(Method.java:585)
   at org.hibernate.property.BasicPropertyAccessor$BasicGetter.get(BasicPropertyAccessor.java:145)
   ... 20 more


Name and version of the database you are using:
HSQLDB 1.8.0, MySQL 5.0, DB2

The generated SQL (show_sql=true):
Code:
Hibernate: select this_.C as C1_0_, this_.D as D1_0_ from TableB this_
Hibernate: select this_.A as A0_0_, this_.B as B0_0_ from TableA this_


Debug level Hibernate log excerpt:
A lot of log before, the few lines before exception:

Code:
12:16:12,518 DEBUG Loader:839 - total objects hydrated: 9
12:16:12,518 DEBUG TwoPhaseLoad:104 - resolving associations for [oo.pojo.TableA#component[A,B]{A=1, B=1}]
12:16:12,519 DEBUG TwoPhaseLoad:132 - adding entity to second-level cache: [oo.pojo.TableA#component[A,B]{A=1, B=1}]
12:16:12,519 DEBUG ReadWriteCache:148 - Caching: oo.pojo.TableA#oo.pojo.TableAId@5b0f
12:16:12,519 ERROR BasicPropertyAccessor:167 - IllegalArgumentException in class: oo.pojo.TableBId, getter method of property: C


I've been debugging this a lot and it seems to me that the problem is in the equals()-method of CacheKey. Since the hashcodes of the two keys collapse (the hashcode for the CacheKey is calculated straigth from the properties of the composite id and when the two tables have same values as their primary key, their hashcodes are same), code enters the equals()-method of CacheKey.

In org.hibernate.cache.CacheKey.equals()-method, in following line of code:
Code:
return type.isEqual(key, that.key, entityMode) &&
     entityOrRoleName.equals(that.entityOrRoleName);

Isn't that in wrong order? Shouldn't CacheKey first check if the entities really are of the same component and only then check if the properties are the same?

Or am I totally on the wrong track here? And in that case, what would be the right way to handle this kind of situation?

Thanks for any input on this,
Teppo


Top
 Profile  
 
 Post subject: Problem when using second level cache and composite id's
PostPosted: Fri May 18, 2007 7:30 am 
Newbie

Joined: Fri May 18, 2007 7:26 am
Posts: 2
We ran into the exact same issue here and your suggestion worked:

> Isn't that in wrong order? Shouldn't CacheKey first check if the entities really are of the same component and only then check if the properties are the same?

I will try to log it as a bug.

Mike


Top
 Profile  
 
 Post subject: Problem when using second level cache and composite id's
PostPosted: Fri May 18, 2007 10:40 am 
Newbie

Joined: Fri May 18, 2007 7:26 am
Posts: 2
Fixed in 3.2.4

Mike


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