小编典典

Hibernate的本机查询和缓存机制

hibernate

我有一个关于Hibernate缓存机制的问题。我在文章中已经读到,在hibernate中执行本机SQLquery会使缓存的所有区域无效,因为hibernate不知道它将影响哪个特定实体。在这里,缓存的所有区域都是在讨论二级缓存或二级缓存(一级缓存,二级缓存)或仅二级缓存或仅一级缓存的各个区域吗?


阅读 220

收藏
2020-06-20

共1个答案

小编典典

文章介绍了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 );
    }
}

因此,如您所见,该区域的所有数据都被驱逐了。

这仅影响二级缓存。每次运行本机查询时,都不会清除第一级缓存(也称为会话),因为这会分离当前的所有“附加实体”,从而给实体状态期望带来意外的后果。但是在每个查询(HQL或本机查询)之前,都会刷新会话,以便在执行查询之前数据库和会话处于同步状态,因此在发出新选择之前,一级缓存是一致的。

整个区域将失效,而不是整个二级缓存失效。实体定义了一个缓存区域,因此更新特定实体表只会删除属于该特定表的所有实体,这些实体受本机查询的影响。

但是,覆盖与本机查询关联的查询空间定义是一种自定义Hibernate的方式,该方式不像使用默认实现那样清除缓存区域。

2020-06-20