My Wiki

August 17, 2006

Evict collection from Hibernate second level cache

Filed under: Hibernate — jaikiran @ 3:59 pm

Hibernate allows persistent objects to be cached in its second level cache(The first level cache in Hibernate is the Session object which is ON by default). Applications can switch on the second level cache.  When a object is being retrieved by the application through Hibernate, Hibernate first checks in its Session cache and then the Second level cache to see if the object has be retrieved already. If it finds it either the Session cache or the Second level cache, it will NOT fire a query to the database.

While configuring second level cache, the object can be cached and also the collections contained in the object can be cached. Have a look at the following example:

<hibernate-mapping default-lazy="false" > 

 <class name="org.myapp.ho.Parent" table="Parent"> 

    <cache usage="read-only" /> 

    <id name="id" type="Integer" column="ID" /> 

  <set name="myChildren"> 

     <cache usage="read-only"> 

     <one-to-many class="org.myapp.ho.Child"> 

  </set> 

 </class> 

</hibernate-mapping>
<hibernate-mapping default-lazy="false" > 

   <class name="org.myapp.ho.Child" table="Child"> 
      <cache usage="read-only" /> 
      <id name="id" type="Integer" column="ID" /> 

   </class> 

</hibernate-mapping>

Note that we have used the cache setting at 3 places:

 1) The org.myapp.ho.Parent object

 2) The “myChildren” collection in the org.myapp.ho.Parent object

 3) The org.myapp.ho.Child object

When you configure a collection to be second level cached in Hibernate, it internally maintains a SEPERATE cache for these collection than the one which it uses to cache the parent objects. So in the example above, the “myChildren” will be cached separately than the org.myapp.ho.Parent object.

 There might be cases where applications would want to evict objects from the cache. If its the Session cache from which the application has to evict the object then the call to Session.evict will cascade even to collections and will evict the collection from the *Session cache*. However, if the object(and the collections contained in it) have to be evicted from the second level cache, then the application has to *explicitly* call the evictCollection method on the SessionFactory to remove the *collection* contained in the Parent object. The reason behind this is, as already mentioned, the collections are cached separately, than the parent objects, in the second level cache.

So, in our example above, if we have to evict the Parent with id 500 and its collection from the second level cache, then here’s what has to be done:

SessionFactory sf = MyUtil.getSessionFactory();

sf.evict(org.myapp.ho.Parent.class,new Integer(500)); //this will evict the Parent Object from the second level cache

sf.evictCollection(org.myapp.ho.Parent.class.getName() +  “.myChildren”, new Integer(500)); //this will evict the collection from the second level cache for the Parent with id=500

The first parameter to the evictCollection method is the ‘roleName’ of the collection. The roleName is formed as follows:

roleName = NameOfTheParentClass + “.” + NameOfTheCollectionInsideTheParent

The second parameter the evictCollection method is the id of the parent object, to which this collection belongs.

Advertisements

4 Comments »

  1. Yes, but why does it not evict org.myapp.ho.Child entities within the cache that were associated to the myChildren Collection whose parent.id = 500 ?

    Comment by Jonathan H — August 18, 2006 @ 1:21 pm

  2. I have a question.

    Lets consider
    1) we are running application in multithread environment.
    2) “Parent” and “myChilderen” has got modified in one transactions from the database (backend)
    3) We want to evict both (parent and childeren) in one go. So that all the threads get either all new or all old.

    How can we ensure this

    Comment by Gajendra — January 30, 2007 @ 4:29 pm

  3. I have a defined <property refering to another table via formula.
    Whenever the main table is updated the changed value of main table comes up. But the value retrived through formula doesn’t get refreshed. How can I clean the Cache? (The changed values of the 2. table comes up when pressed)

    Comment by KAZIM GORENEKLI — January 5, 2009 @ 7:39 am

  4. It can be not transactional safe to do it on session factory:

    sf.evictCollection(org.myapp.ho.Parent.class.getName() + “.myChildren”, new Integer(500));

    My solution is:

    if (MYCOLLECTION instanceof AbstractPersistentCollection) ((AbstractPersistentCollection) MYCOLLECTION).dirty();

    Which is default behaviour of add/remove item to hibernate collection

    Comment by l0co — May 19, 2010 @ 9:46 pm


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: