Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Native query and caching mechanism of Hibernate

I have a question regarding Hibernate caching mechanism.I have read in the articles that native SQLquery execution in hibernate, invalidates all regions of cache because hibernate does not have any idea regarding which particular entity it is going to affect. Here all regions of cache means are we talking about various regions of the second level cache or both levels of cache(first level cache,second level cache) or only second level cache or only first level cache?

like image 935
Beast Avatar asked May 31 '14 19:05

Beast


1 Answers

Using SQLQuery, Hibernate couldn't know what cache regions you might affect, but luckily you can explicitly instruct it:

SQLQuery sqlQuery = session.createSQLQuery(
    "UPDATE CUSTOMER SET ... WHERE ..."); 
sqlQuery.addSynchronizedEntityClass(Person.class); int
int updateCount = sqlQuery.executeUpdate();

This way it knows what query caches to invalidate, otherwise it may discard everything:

private static class EntityCleanup {
    private final EntityRegionAccessStrategy cacheAccess;
    private final SoftLock cacheLock;

    private EntityCleanup(EntityRegionAccessStrategy cacheAccess) {
        this.cacheAccess = cacheAccess;
        this.cacheLock = cacheAccess.lockRegion();
        cacheAccess.removeAll();
    }

    private void release() {
        cacheAccess.unlockRegion( cacheLock );
    }
}

private static class CollectionCleanup {
    private final CollectionRegionAccessStrategy cacheAccess;
    private final SoftLock cacheLock;

    private CollectionCleanup(CollectionRegionAccessStrategy cacheAccess) {
        this.cacheAccess = cacheAccess;
        this.cacheLock = cacheAccess.lockRegion();
        cacheAccess.removeAll();
    }

    private void release() {
        cacheAccess.unlockRegion( cacheLock );
    }
}

private class NaturalIdCleanup {
    private final NaturalIdRegionAccessStrategy naturalIdCacheAccessStrategy;
    private final SoftLock cacheLock;

    public NaturalIdCleanup(NaturalIdRegionAccessStrategy naturalIdCacheAccessStrategy) {
        this.naturalIdCacheAccessStrategy = naturalIdCacheAccessStrategy;
        this.cacheLock = naturalIdCacheAccessStrategy.lockRegion();
        naturalIdCacheAccessStrategy.removeAll();
    }

    private void release() {
        naturalIdCacheAccessStrategy.unlockRegion( cacheLock );
    }
}

So, as you can see the whole data from the Region is evicted.

This only affects the second-level cache. The first level cache (a.k.a. Session) is not cleared every time you run a native query, because that would detach all your current "attached entities", having unexpected consequences in entity state expectations. But before every query (HQL or native) the session is flushed so the DB and the session are in sync prior to executing the query, hence the 1st level cache is consistent before issuing a new select.

A whole region would get invalidated, not the whole second-level cache. An entity defines a cache region, so updating a specific entity table would only remove all the entities that belong to that particular table(s) that were affected by the native query.

But overriding the query-space definition associated with a native query is a way to customize Hibernate not to clear the cache region as it would do using the default implementation.

like image 82
Vlad Mihalcea Avatar answered Sep 28 '22 19:09

Vlad Mihalcea