Native query and caching mechanism of Hibernate

前端 未结 1 1196
忘了有多久
忘了有多久 2020-12-29 12:55

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 hib

相关标签:
1条回答
  • 2020-12-29 13:46

    This article explains how the Hibernate query cache works and the effect of native queries over existing cache entries.

    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 to a native query is a way to customize Hibernate not to clear the cache region as it would do using the default implementation.

    0 讨论(0)
提交回复
热议问题