-->
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.  [ 6 posts ] 
Author Message
 Post subject: setCacheable(true) results in an IllegalArgumentException...
PostPosted: Tue Jul 21, 2009 4:35 pm 
Beginner
Beginner

Joined: Wed Dec 10, 2008 5:59 am
Posts: 47
I've got a tree structure of Node objects (Node extends BaseEntity). Each node can have one parent Node object and many children Node objects. I retrieve this structure from the database with one single HQL select statement ("from Node n"). When i invoke setCacheable(false), the tree structure loads just fine.

However; when i invoke setCacheable(true), i get an IllegalArgumentException telling me that "object is not an instance of declaring class". Strange!

Code:
ERROR BasicPropertyAccessor:167 - IllegalArgumentException in class: com.tracker.db.entities.Node, getter method of property: id
[...]
org.hibernate.PropertyAccessException: IllegalArgumentException occurred calling getter of com.tracker.db.entities.Node.id
[...]
Caused by: java.lang.IllegalArgumentException: object is not an instance of declaring class


I've tried a lot of things to solve this, of which the most "drastic" has been:

(1) Removed almost all properties besides from the absolutely necessary ones from the mappings document.
(2) Moved all fields from BaseEntity into Node so that Node no longer extends BaseEntity.
(3) Removed fetch join of the children and parent properties in my HQL.

However, nothing really solves the problem. But, somehow the cache must be doing something that makes this go wrong? So, if anyone have any insight to share on this one i would be very, very happy and thankful.

Mapping file and code:

Code:
<hibernate-mapping>
  <class name="com.tracker.db.entities.Node" table="keywordnode">
  <cache usage="read-write"/>
  <id column="id" length="36" name="id" type="com.tracker.db.usertypes.CustomUUID"/>
  <version column="updated" name="updated" type="java.util.Calendar" unsaved-value="null"/>
  <property column="name" length="200" name="name" type="java.lang.String"/>
  <many-to-one name="parent" cascade="none" class="com.tracker.db.entities.Node" column="parent_id"/>
  <bag cascade="none" inverse="true" name="children" order-by="name asc">
    <cache usage="read-write"/>
    <key column="parent_id"/>
    <one-to-many class="com.tracker.db.entities.Node"/>
  </bag>
</hibernate-mapping>


Code:
Query q = currentSession.createQuery("from Node n left join fetch n.parent left join fetch n.children");
q.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
q.setCacheable(true);
q.list();


Code:
public class BaseEntity implements Serializable {
  private java.util.UUID id = null;
  private java.util.Calendar updated = null;

  public java.util.UUID getId() {}
  public void setId(java.util.UUID id) {}
  public void setUpdated(java.util.Calendar updated) {}
  public java.util.Calendar getUpdated() {}
}


Code:
public class Node extends BaseEntity implements Comparable<Node> {
  private String name = "";
  private Node parent = null;
  private java.util.List children = new java.util.ArrayList();

  public String getName() {}
  public void setName(String name) {}
  public Node getParent() {}
  public void setParent(Node parent) {}
  public java.util.List getChildren() {}
  public void setChildren(java.util.List children) {}
}


Top
 Profile  
 
 Post subject: Re: setCacheable(true) results in an IllegalArgumentException...
PostPosted: Wed Jul 22, 2009 1:55 am 
Beginner
Beginner

Joined: Wed Dec 10, 2008 5:59 am
Posts: 47
It appears that using Criteria.DISTINCT_ROOT_ENTITY does not always work that well in combination with the query cache. The HQL i use to retrieve the tree structure from the database eagerly fetches children of all nodes. I invoked setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY) in order to retrieve only disctinct objects from the query (references between a node and its children would of course be in place). This did (as shown in the post above) not work very well.

However; using the "distinct" keyword in my HQL sorted the problem. So, instead of this:

Code:
Query q = currentSession.createQuery("select distinct k from Keyword k left join fetch k.children left join fetch k.parent");
q.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
q.setCacheable(true);
q.list();


i did this:

Code:
Query q = getSession().createQuery("select distinct k from Keyword k left join fetch k.children left join fetch k.parent");
q.setCacheable(true);
q.list();


Top
 Profile  
 
 Post subject: Re: setCacheable(true) results in an IllegalArgumentException...
PostPosted: Wed Jul 22, 2009 3:36 am 
Beginner
Beginner

Joined: Wed Dec 10, 2008 5:59 am
Posts: 47
It seems that my tree structure did not get fully cached just by enabling 2nd level cache and query cache. My assumptions were as follows:


The q.list() will return not only the hierarchy root entity, but all entities existing in the whole tree structure. I therefore thought that by merely iterating the q.list(), i would cache all entities in the tree.


However, it turned out that the children collections were not cached. I'm not 100% sure why this occurs, but i can think of two explanations:

(1). The children collections not is populated by the objects that i find in the q.list(). Instead, the children collections are populated by objects that are constructed based on the join values in the SQL query. So, as the children collections and the q.list() does not hold references to the same objects, the children collections will not be cached when i iterate the q.list(). However! The 2nd level cache does not cache objects, only PK's and their values...so this should not really be an issue.

(2). The children collections lives in com.tracker.db.entities.Node.children and the hierarchy tree cache lives in com.tracker.db.entities.Node. So, the children collections cache is never really populated since i never iterate the children collections.

So, I solved this by iterating q.list() and invoking Hibernate.initialize() on the child collection on all nodes. I guess i also could have just run an iteration on each of the children in each of the collections to achieve the same (that is, cache the children collections).

After doing the above, the entire tree structure is now being cached.


Top
 Profile  
 
 Post subject: Re: setCacheable(true) results in an IllegalArgumentException...
PostPosted: Sun Aug 02, 2009 2:36 am 
Newbie

Joined: Sat May 30, 2009 2:47 am
Posts: 12
No, the children collection is cached, however, when you read query result from cache, hibernate only initialize the parent entity, without fully initializing the child collection.

I know by calling Hibernate.initialize() will solve the problem. But it makes the code not clean, and it is repeating the fetch logic:

org.hibernate.Criteria criteria = session.createCriteria(Podcast.class);
criteria.setFetchMode("podcastCategoryMappings", FetchMode.JOIN);
criteria.add(Restrictions.in("id", podIds));
criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
criteria.addOrder(Order.asc("title"));

criteria.setCacheable(true); // turn on cache


podcasts = criteria.list();

for (Podcast podcast: podcasts) {
//Here I have to call Hibernate.initilize for hibernate to remember to fetch the collection entity from cache.
Hibernate.initialize(podcast.getPodcastCategoryMappings());
}


I will show later the hibernate cache log to show you hibernate did put the collection objects into cache, but just fail to read it from cache in the case of query cache. I


Top
 Profile  
 
 Post subject: Re: setCacheable(true) results in an IllegalArgumentException...
PostPosted: Sun Aug 02, 2009 2:40 am 
Newbie

Joined: Sat May 30, 2009 2:47 am
Posts: 12
This is the output if I don't explicitly call Hibernate.initialize():

Ideally, we shall see cache hit for all those PodcastCategoryMapping objects, but we only see the root object cache hit, "Podcast".

Hibernate: select this_.ID as ID1_1_, this_.RSS_FEED_URL as RSS2_1_1_, this_.TITLE as TITLE1_1_, this_.SUBTITLE as SUBTITLE1_1_, this_.DESCRIPTION as DESCRIPT5_1_1_, this_.SOURCE_ID as SOURCE6_1_1_, this_.POSTER_FILE_URL as POSTER7_1_1_, this_.IS_VALID as IS8_1_1_, this_.IS_PUBLISHED as IS9_1_1_, this_.AUTHOR as AUTHOR1_1_, this_.KEYWORDS as KEYWORDS1_1_, this_.LAST_UPDATED as LAST12_1_1_, this_.LAST_UPDATED_BY as LAST13_1_1_, this_.EXPLICIT as EXPLICIT1_1_, this_.LAST_BUILD_DATE as LAST15_1_1_, this_.ITUNES_CATEGORY as ITUNES16_1_1_, this_.primary_category_id as primary17_1_1_, podcastcat2_.POD_ID as POD2_3_, podcastcat2_.ID as ID3_, podcastcat2_.ID as ID3_0_, podcastcat2_.POD_ID as POD2_3_0_, podcastcat2_.CAT_ID as CAT3_3_0_, podcastcat2_.POS as POS3_0_ from podcasts_catalog.podcast this_ left outer join podcasts_catalog.podcast_category_mapping podcastcat2_ on this_.ID=podcastcat2_.POD_ID where this_.ID in (?) order by this_.TITLE asc
TRACE | 2009-08-01 23:36:49,125 | org.hibernate.cache.ReadWriteCache | 173 | Caching: com.pcs.core.db.entities.PodcastCategoryMapping#1
TRACE | 2009-08-01 23:36:49,125 | org.hibernate.cache.ReadWriteCache | 185 | Cached: com.pcs.core.db.entities.PodcastCategoryMapping#1
TRACE | 2009-08-01 23:36:49,125 | org.hibernate.cache.ReadWriteCache | 173 | Caching: com.pcs.core.db.entities.Podcast#1
TRACE | 2009-08-01 23:36:49,125 | org.hibernate.cache.ReadWriteCache | 185 | Cached: com.pcs.core.db.entities.Podcast#1
TRACE | 2009-08-01 23:36:49,125 | org.hibernate.cache.ReadWriteCache | 173 | Caching: com.pcs.core.db.entities.PodcastCategoryMapping#2
TRACE | 2009-08-01 23:36:49,125 | org.hibernate.cache.ReadWriteCache | 185 | Cached: com.pcs.core.db.entities.PodcastCategoryMapping#2
TRACE | 2009-08-01 23:36:49,125 | org.hibernate.cache.ReadWriteCache | 173 | Caching: com.pcs.core.db.entities.PodcastCategoryMapping#3
TRACE | 2009-08-01 23:36:49,125 | org.hibernate.cache.ReadWriteCache | 185 | Cached: com.pcs.core.db.entities.PodcastCategoryMapping#3
TRACE | 2009-08-01 23:36:49,125 | org.hibernate.cache.ReadWriteCache | 173 | Caching: com.pcs.core.db.entities.PodcastCategoryMapping#4
TRACE | 2009-08-01 23:36:49,125 | org.hibernate.cache.ReadWriteCache | 185 | Cached: com.pcs.core.db.entities.PodcastCategoryMapping#4
TRACE | 2009-08-01 23:36:49,140 | org.hibernate.cache.ReadWriteCache | 173 | Caching: com.pcs.core.db.entities.PodcastCategoryMapping#5
TRACE | 2009-08-01 23:36:49,140 | org.hibernate.cache.ReadWriteCache | 185 | Cached: com.pcs.core.db.entities.PodcastCategoryMapping#5
TRACE | 2009-08-01 23:36:49,140 | org.hibernate.cache.ReadWriteCache | 173 | Caching: com.pcs.core.db.entities.Podcast.podcastCategoryMappings#1
TRACE | 2009-08-01 23:36:49,140 | org.hibernate.cache.ReadWriteCache | 185 | Cached: com.pcs.core.db.entities.Podcast.podcastCategoryMappings#1
DEBUG | 2009-08-01 23:36:49,140 | org.hibernate.cache.StandardQueryCache | 94 | caching query results in region: org.hibernate.cache.StandardQueryCache; timestamp=5116702756352000
DEBUG | 2009-08-01 23:36:49,156 | org.hibernate.cache.StandardQueryCache | 127 | checking cached query results in region: org.hibernate.cache.StandardQueryCache
DEBUG | 2009-08-01 23:36:49,156 | org.hibernate.cache.StandardQueryCache | 185 | Checking query spaces for up-to-dateness: [podcasts_catalog.podcast]
DEBUG | 2009-08-01 23:36:49,156 | org.hibernate.cache.StandardQueryCache | 142 | returning cached query results
DEBUG | 2009-08-01 23:36:49,156 | org.hibernate.cache.StandardQueryCache | 127 | checking cached query results in region: org.hibernate.cache.StandardQueryCache
DEBUG | 2009-08-01 23:36:49,156 | org.hibernate.cache.StandardQueryCache | 185 | Checking query spaces for up-to-dateness: [podcasts_catalog.podcast]
DEBUG | 2009-08-01 23:36:49,156 | org.hibernate.cache.StandardQueryCache | 142 | returning cached query results
DEBUG | 2009-08-01 23:36:49,156 | org.hibernate.cache.StandardQueryCache | 127 | checking cached query results in region: org.hibernate.cache.StandardQueryCache
DEBUG | 2009-08-01 23:36:49,156 | org.hibernate.cache.StandardQueryCache | 185 | Checking query spaces for up-to-dateness: [podcasts_catalog.podcast]
DEBUG | 2009-08-01 23:36:49,156 | org.hibernate.cache.StandardQueryCache | 142 | returning cached query results
TRACE | 2009-08-01 23:36:49,156 | org.hibernate.cache.ReadWriteCache | 100 | Cache lookup: com.pcs.core.db.entities.Podcast#1
TRACE | 2009-08-01 23:36:49,156 | org.hibernate.cache.ReadWriteCache | 110 | Cache hit: com.pcs.core.db.entities.Podcast#1


Top
 Profile  
 
 Post subject: Re: setCacheable(true) results in an IllegalArgumentException...
PostPosted: Sun Aug 02, 2009 2:43 am 
Newbie

Joined: Sat May 30, 2009 2:47 am
Posts: 12
With that one line of Hibernate.initialize(podcastCategoryMapping), you will see almost the same output, but additional cache hits:

DEBUG | 2009-08-01 23:41:06,218 | org.hibernate.cache.StandardQueryCache | 185 | Checking query spaces for up-to-dateness: [podcasts_catalog.podcast]
DEBUG | 2009-08-01 23:41:06,218 | org.hibernate.cache.StandardQueryCache | 142 | returning cached query results
TRACE | 2009-08-01 23:41:06,218 | org.hibernate.cache.ReadWriteCache | 100 | Cache lookup: com.pcs.core.db.entities.Podcast#1
TRACE | 2009-08-01 23:41:06,218 | org.hibernate.cache.ReadWriteCache | 110 | Cache hit: com.pcs.core.db.entities.Podcast#1
TRACE | 2009-08-01 23:41:06,218 | org.hibernate.cache.ReadWriteCache | 100 | Cache lookup: com.pcs.core.db.entities.Podcast.podcastCategoryMappings#1
TRACE | 2009-08-01 23:41:06,218 | org.hibernate.cache.ReadWriteCache | 110 | Cache hit: com.pcs.core.db.entities.Podcast.podcastCategoryMappings#1
TRACE | 2009-08-01 23:41:06,218 | org.hibernate.cache.ReadWriteCache | 100 | Cache lookup: com.pcs.core.db.entities.PodcastCategoryMapping#5
TRACE | 2009-08-01 23:41:06,218 | org.hibernate.cache.ReadWriteCache | 110 | Cache hit: com.pcs.core.db.entities.PodcastCategoryMapping#5
TRACE | 2009-08-01 23:41:06,218 | org.hibernate.cache.ReadWriteCache | 100 | Cache lookup: com.pcs.core.db.entities.PodcastCategoryMapping#4
TRACE | 2009-08-01 23:41:06,218 | org.hibernate.cache.ReadWriteCache | 110 | Cache hit: com.pcs.core.db.entities.PodcastCategoryMapping#4
TRACE | 2009-08-01 23:41:06,218 | org.hibernate.cache.ReadWriteCache | 100 | Cache lookup: com.pcs.core.db.entities.PodcastCategoryMapping#1
TRACE | 2009-08-01 23:41:06,218 | org.hibernate.cache.ReadWriteCache | 110 | Cache hit: com.pcs.core.db.entities.PodcastCategoryMapping#1
TRACE | 2009-08-01 23:41:06,218 | org.hibernate.cache.ReadWriteCache | 100 | Cache lookup: com.pcs.core.db.entities.PodcastCategoryMapping#3
TRACE | 2009-08-01 23:41:06,218 | org.hibernate.cache.ReadWriteCache | 110 | Cache hit: com.pcs.core.db.entities.PodcastCategoryMapping#3
TRACE | 2009-08-01 23:41:06,218 | org.hibernate.cache.ReadWriteCache | 100 | Cache lookup: com.pcs.core.db.entities.PodcastCategoryMapping#2
TRACE | 2009-08-01 23:41:06,218 | org.hibernate.cache.ReadWriteCache | 110 | Cache hit: com.pcs.core.db.entities.PodcastCategoryMapping#2
pod id: 1
pod title/id: title 5887/1 category id: ff80808122a981f00122a981f364001b
pod title/id: title 5887/1 category id: ff80808122a981f00122a981f3260015
pod title/id: title 5887/1 category id: ff80808122a981f00122a981f2b9000b
pod title/id: title 5887/1 category id: ff80808122a981f00122a981f2e7000f
pod title/id: title 5887/1 category id: ff80808122a981f00122a981f374001c


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