我有一个关于Hibernate缓存机制的问题。我在文章中读到,当Hibernate执行本地SQL查询时,会使所有缓存区域失效,因为Hibernate不知道它将影响哪个特定实体。这里提到的所有缓存区域是指第二级缓存的各个区域,还是指两级缓存(一级缓存、二级缓存)的所有区域,或者只是指第二级缓存或仅指一级缓存?
我有一个关于Hibernate缓存机制的问题。我在文章中读到,当Hibernate执行本地SQL查询时,会使所有缓存区域失效,因为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 );
}
}
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 );
}
}
因此,正如您所看到的,Region
的所有数据都被逐出了。
这只影响了二级缓存。每次运行本机查询时,不会清除一级缓存(也称为Session
),因为这将分离所有当前的“已附加实体”,导致实体状态期望产生意外后果。但在每个查询(HQL或本机)之前,会刷新会话以使数据库和会话同步,因此在发出新的select之前,第一级缓存是一致的。
整个区域将被无效化,而不是整个二级缓存。实体定义了一个缓存区域,因此更新特定实体表仅会删除受本机查询影响的那些特定表中属于该特定表的所有实体。
但是,覆盖与本机查询相关联的查询空间定义是一种自定义Hibernate的方法,以便不清除缓存区域,就像使用默认实现一样。