简体   繁体   中英

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?

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.

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

In my case, I disable the minimal put setting in hibernate and then the query cache will automatically update all the related second level cache each time when SQL issued.

I think this is the solution to your question "to force the query to update also the L2 cache" (This also bug me a long time.....)

<property name="hibernate.cache.use_minimal_puts" value="false"/>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM