20.2. 二级缓存(The Second Level Cache)

优质
小牛编辑
136浏览
2023-12-01

Hibernate 的 Session 在事务级别进行持久化数据的缓存操作。 当然,也有可能分别为每个类(或集合),配置集群、或 JVM 级别(SessionFactory 级别)的缓存。你甚至可以为之插入一个集群的缓存。注意,缓存永远不知道其他应用程序对持久化仓库(数据库)可能进行的修改 (即使可以将缓存数据设定为定期失效)。

通过在 hibernate.cache.provider_class 属性中指定 org.hibernate.cache.CacheProvider 的某个实现的类名,你可以选择让 Hibernate 使用哪个缓存实现。Hibernate 打包一些开源缓存实现,提供对它们的内置支持(见下表)。除此之外,你也可以实现你自己的实现,将它们插入到系统中。注意,在 3.2 版本之前,默认使用 EhCache 作为缓存实现,但从 3.2 起就不再这样了。

表 20.1. 缓存策略提供商(Cache Providers)

CacheProvider classTypeCluster SafeQuery Cache Supported
Hashtable (not intended for production use)org.hibernate.cache.HashtableCacheProvidermemoryyes
EHCacheorg.hibernate.cache.EhCacheProvidermemory,diskyes
OSCacheorg.hibernate.cache.OSCacheProvidermemory,diskyes
SwarmCacheorg.hibernate.cache.SwarmCacheProviderclustered (ip multicast)yes (clustered invalidation)
JBoss Cache 1.xorg.hibernate.cache.TreeCacheProviderclustered (ip multicast), transactionalyes (replication)yes (clock sync req.)
JBoss Cache 2org.hibernate.cache.jbc.JBossCacheRegionFactoryclustered (ip multicast), transactionalyes (replication or invalidation)yes (clock sync req.)

20.2.1. 缓存映射(Cache mappings)

类或者集合映射的“<cache> 元素”可以有下列形式:

<cache
    usage="tra(1)nsactional|read-write|nonstrict-read-write|read-only"
    region="Re(2)gionName"
    include="a(3)ll|non-lazy"
/>

1

usage(必须)说明了缓存的策略:transactionalread-writenonstrict-read-writeread-only

2

region (可选,默认为类或者集合的名字(class or collection role name)) 指定第二级缓存的区域名(name of the second level cache region)

3

include(可选,默认为 allnon-lazy 当属性级延迟抓取打开时,标记为 lazy="true" 的实体的属性可能无法被缓存

另外(首选?),你可以在hibernate.cfg.xml 中指定 <class-cache><collection-cache> 元素。

这里的 usage 属性指明了缓存并发策略(cache concurrency strategy)

20.2.2. 策略:只读缓存(Strategy:read only)

如果你的应用程序只需读取一个持久化类的实例,而无需对其修改, 那么就可以对其进行只读 缓存。这是最简单,也是实用性最好的方法。甚至在集群中,它也能完美地运作。

<class name="eg.Immutable" mutable="false">
    <cache usage="read-only"/>
    ....
</class
>

20.2.3. 策略:读写/缓存(Strategy:read/write)

如果应用程序需要更新数据,那么使用读/写缓存 比较合适。 如果应用程序要求“序列化事务”的隔离级别(serializable transaction isolation level),那么就决不能使用这种缓存策略。 如果在 JTA 环境中使用缓存,你必须指定 hibernate.transaction.manager_lookup_class 属性的值, 通过它,Hibernate 才能知道该应用程序中 JTA 的TransactionManager的具体策略。 在其它环境中,你必须保证在 Session.close()、或 Session.disconnect() 调用前, 整个事务已经结束。 如果你想在集群环境中使用此策略,你必须保证底层的缓存实现支持锁定(locking)。Hibernate 内置的缓存策略并不支持锁定功能。

<class name="eg.Cat" .... >
    <cache usage="read-write"/>
    ....
    <set name="kittens" ... >
        <cache usage="read-write"/>
        ....
    </set>
</class
>

20.2.4. 策略:非严格读/写缓存(Strategy:nonstrict read/write)

如果应用程序只偶尔需要更新数据(也就是说,两个事务同时更新同一记录的情况很不常见),也不需要十分严格的事务隔离,那么比较适合使用非严格读/写缓存策略。如果在 JTA 环境中使用该策略,你必须为其指定 hibernate.transaction.manager_lookup_class 属性的值,在其它环境中,你必须保证在Session.close()、或 Session.disconnect() 调用前,整个事务已经结束。

20.2.5. 策略:事务缓存(transactional)

Hibernate 的事务缓存策略提供了全事务的缓存支持,例如对 JBoss TreeCache 的支持。这样的缓存只能用于 JTA 环境中,你必须指定为其 hibernate.transaction.manager_lookup_class 属性。

20.2.6. 各种缓存提供商/缓存并发策略的兼容性

重要

没有一种缓存提供商能够支持上列的所有缓存并发策略。下表中列出了各种提供器、及其各自适用的并发策略。

没有一种缓存提供商能够支持上列的所有缓存并发策略。下表中列出了各种提供器、及其各自适用的并发策略。

表 20.2. 各种缓存提供商对缓存并发策略的支持情况(Cache Concurrency Strategy Support)

Cacheread-onlynonstrict-read-writeread-writetransactional
Hashtable (not intended for production use)yesyesyes
EHCacheyesyesyes
OSCacheyesyesyes
SwarmCacheyesyes
JBoss Cache 1.xyesyes
JBoss Cache 2yesyes