问题描述
我有一个关于Hibernate缓存机制的问题。我已经读过文章中说,在hibernate中执行原生SQLquery,会使缓存的所有区域失效,因为hibernate并不知道它将影响哪个特定实体。在这里,缓存手段的所有区域是指第二级缓存的各个区域还是缓存级别(第一级缓存,第二级缓存)或仅第二级缓存或仅第一级缓存? 解释了Hibernate查询缓存如何工作以及原生查询对现有缓存条目的影响。使用SQLQuery, Hibernate无法知道您可能会影响哪些缓存区域,但幸运的是您可以明确指示它:
SQLQuery sqlQuery = session.createSQLQuery (
UPDATE CUSTOMER SET ... WHERE ...);
sqlQuery.addSynchronizedEntityClass(Person.class); int
int updateCount = sqlQuery.executeUpdate();
这样它就知道查询缓存是无效的,否则可能会丢弃所有内容:
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);
}
}
私有静态类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);
$ b因此,你可以看到来自地区被驱逐。
这只影响二级缓存。第一级缓存(a.k.a. Session)在每次运行本机查询时都不会被清除,因为它会分离所有当前的附属实体,从而对实体状态的预期产生意想不到的后果。但在每次查询(HQL或本地)之前,会话都会被刷新,因此数据库和会话在执行查询之前是同步的,因此第一级缓存在发出新选择前是一致的。
整个区域会失效,而不是整个二级缓存。一个实体定义了一个缓存区域,因此更新一个特定的实体表只会删除属于受本地查询影响的特定表的所有实体。
但是重写与本地查询关联的查询空间定义是一种自定义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?
解决方案 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.
这篇关于Hibernate的本地查询和缓存机制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!