Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate cache: Are objects returned by a cached query stored in L2 cache?

We're using hibernate4 and ehcache in our project. We mostly work on immutable objects, so caching is a feature which fits nicely in our application. While trying to enable query cache, we ran into the following problem:

Assuming we have the following entity:

@Entity 
@Table(name = "DOGS")
@Immutable 
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
class Dog {
  @Id @Column
  Long id;
  @Column
  String name;
}

and the query:

Criteria criteria = session.createCriteria(Dog.class);
criteria.add(Restrictions.in("id", ids));
criteria.setCacheable(true);

The query cache timeToLive is set to about 3/4 of the Dog timeToLive. Here's the scenario (please correct me if I made a wrong assumption):

  1. The first time the query is called (assuming the cache is empty), it is executed and the returned Dog instances are stored in the second level cache. Also, the Dog ids are stored in the query cache.
  2. The second time the query is called (the Dog ids are in the query cache and the Dog objects are in the L2 cache), everything works fine. The query cache returns the ids and the Dogs are fetched from L2.
  3. When the query cache expires (but the L2 cache is still valid), the query re-runs and caches the Dog ids.
  4. Now the L2 cache expires for the Dog object and all objects are evicted from cache. The query cache still has the ids cached, so hibernate fetches the Dog objects one by one, which takes forever.

The 3rd point is bugging me. The query cache got invalidated and re-ran on the database, fetching the Dog objects, but the Dog objects were not updated in the L2 cache. It looks like the query only updated the dog ids in the query cache, but not the L2 cache.

Is there a way to force the query to update also the L2 cache? Perhaps this scenario is to be handled differently?

like image 395
Wojciech Górski Avatar asked Feb 20 '13 18:02

Wojciech Górski


2 Answers

See Second Level cache is for Object/Pojos you specify for getting cached. But Query cache is created for specific queries. So it seems natural that both are unrelated and second level cache will not get updated when your query cache gets updated. That's why there is different configuration for both of them. You can either refer Hibernate Documentation or this link or this link may help you understand things.

like image 57
Ajay Bhojak Avatar answered Nov 15 '22 00:11

Ajay Bhojak


I tried this and worked for me in the past to clean L2 cache

//clear the cache entity
sf.getCache().evictEntity(Dog.class,12345); //Entity with 12345 id

//or clear a collection 
sf.getCache().evictCollection("com.package.Dog.getCol",12345); //Collections
//Note: the collection contains the name of the fully qualified class.

//then, run the query

Hope it helps

like image 40
victoriza Avatar answered Nov 14 '22 22:11

victoriza