How to fix Hibernate Query Cache for Grails 1.3.5

To speed up our Grails-application we’ve decided to use hibernates’ second-level- and query-cache. To do so, we performed the following steps:

  • Added appropriate caching-xml-elements to our ehcache.xml (resides within grails-app/conf)
  • Enabled query-cache (“cache.use_query_cache=true” within DataSource.groovy)
  • Enabled the 2nd level cache for the relevant entities
  • Enabled the Query-Cache for a specific query via (SomeClass.findAllByX(someX, [cache: true]))

To test the cache, we implemented an integration-test. Whenever we created an entity and asked for it multiple times the cache worked as expected. The first retrieval-attempt lead to a cache-miss, the following calls to cache-hits. In a next step we adapted the test a little: we changed the entity AFTER it was added to the query-cache and tried afterwards to retrieve it again and again. But the cache just produced cache-misses. After some debugging and reading we discovered that this behaviour was the result of a bug of the hibernate-version used by Grails 1.3.5. You can find details about  this here. In addition to the linked blog-post we will describe here in more detail what you have to do to fix the bug so that you can really use the hibernate-cache with this grails-version.

  1. Download hibernate-distribution-3.3.1.GA-dist.zip from http://sourceforge.net/projects/hibernate/files/
  2. You are just interested in the “project”-folder, so unzip it to a separate project-director
  3. Open the pom with your favourite java-ide (we are using IntelliJ for this)
  4. Download the latest 1.5 jdk and install it. Adapt the project to use this jdk
  5. Open org.hibernate.cache.StandardQueryCache and go to the “put” method. There you will find the following line (around line 90):

    ...
    Long ts = Long.valueOf( session.getTimestamp() );
    ...

    Replace it with the following code:

    ...
    Long ts = Long.valueOf(cacheRegion.nextTimestamp());
    ...
  6. Use the “package” target of “Hibernate Core” to create your customized jar. When Maven have problems to download some of the necessary dependencies (e.g. JAAS jar), you have to download them manually and add them to the appropriate folder within /youruserhome/.m2/repository/
  7. Finally you have your own version of hibernate-core.jar -> add it to your grails installation by copying it to GRAILS_HOME/lib. You will have to overwrite the existing hibernate-core-3.3.1.GA.jar with your customized jar
  8. There is just one step left: don’t forget to also replace the hibernate-core-3.3.1.GA.jar from your local ivy cache. You can find it under/youruserhome/.ivy2/cache. If you don’t replace this jar, Grails will replace your custom  hibernate version with the old one and you will see no effect.

Conclusion

To create a “custom build” of hibernate is no big deal, after you found the sources and all the dependencies you need. But from my point of view you shouldn’t need to do this for an “ordinary feature” like query-caching. I’m not quite sure why Grails ships such an outdated version of hibernate: the current version is 3.6.0 and the version which comes with Grails is 3.3.1.

Advertisements

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