Using Grails console-plugin to Interactively Evict Hibernate’s Second Level Cache
It can be very handy to use Grails console-plugin to investigate database-cache-related issues. For instance in a case where everything works as expected but still a certain value is not displayed on a view – the reason can be that an old value is provided due to a configured database-caching. In the following case it’s a Hibernate’s second-level cache configured in conjunction with Grails and the following simple domain-model:
[groovy title="Company.groovy" highlight="6"] class Company { static hasMany = [isins: ISIN] Set<ISIN> isins static mapping = { isins lazy: false, cache: true } } [/groovy]
[groovy title="ISIN.groovy"] class ISIN { String name static constraints = { name blank: false, unique: true } } [/groovy]
The Company domain is using Hibernate’s second level cache to cache a collection (association) of ISIN domain-objects. As an addition the collection is fetched non-lazy (eager) which avoids GORM firing N+1 queries when iterating over the ISINs.
—
But back to the original problem – to ensure that a value is not fetched out of a cache it is best to just empty that cache. Luckily, we can use the SessionFactory of Hibernate to do that. Having a Grails-setup and using the Grails console-plugin it’s easy as a one-liner on the interactive prompt to say that we want to evict the second level cache for a given collection:
[groovy title="interactive grails-console" highlight="9"] // Groovy Code here // Implicit variables include: // ctx: the Spring application context // grailsApplication: the Grails application // config: the Grails configuration // request: the HTTP request // session: the HTTP session ctx.sessionFactory.evictCollection('Company.isins') [/groovy]
The groovy-script gets the Hibernate SessionFactory from Spring’s application-context and calls evictCollection which according to the source-code of evictCollection delegates to a CollectionPersister that defines a contract between the persistence strategy and the actual persistent collection. Hibernate then takes the underlying CollectionRegionAccessStrategy for the ISIN-collection and forcibly evicts all items from the cache immediately without regard for transaction-isolation.