百度首页 | 百度空间
 
查看文章
 
19.2. The Second Level Cache
2007-10-11 14:51

19.2. The Second Level Cache

A Hibernate Session is a transaction-level cache of persistent data. It is possible to configure a cluster or JVM-level (SessionFactory-level) cache on a class-by-class and collection-by-collection basis. You may even plug in a clustered cache. Be careful. Caches are never aware of changes made to the persistent store by another application (though they may be configured to regularly expire cached data).

You have the option to tell Hibernate which caching implementation to use by specifying the name of a class that implements org.hibernate.cache.CacheProvider using the property hibernate.cache.provider_class. Hibernate comes bundled with a number of built-in integrations with open-source cache providers (listed below); additionally, you could implement your own and plug it in as outlined above. Note that versions prior to 3.2 defaulted to use EhCache as the default cache provider; that is no longer the case as of 3.2.

Table 19.1. Cache Providers

Cache Provider class Type Cluster Safe Query Cache Supported
Hashtable (not intended for production use) org.hibernate.cache.HashtableCacheProvider memory yes
EHCache org.hibernate.cache.EhCacheProvider memory, disk yes
OSCache org.hibernate.cache.OSCacheProvider memory, disk yes
SwarmCache org.hibernate.cache.SwarmCacheProvider clustered (ip multicast) yes (clustered invalidation)
JBoss TreeCache org.hibernate.cache.TreeCacheProvider clustered (ip multicast), transactional yes (replication) yes (clock sync req.)

19.2.1. Cache mappings

The <cache> element of a class or collection mapping has the following form:

<cache 
     usage="transactional|read-write|nonstrict-read-write|read-only"  (1)
     region="RegionName"                                              (2)
     include="all|non-lazy"                                           (3)
/>
(1)

usage (required) specifies the caching strategy: transactional, read-write, nonstrict-read-write or read-only

(2)

region (optional, defaults to the class or collection role name) specifies the name of the second level cache region

(3)

include (optional, defaults to all) non-lazy specifies that properties of the entity mapped with lazy="true" may not be cached when attribute-level lazy fetching is enabled

Alternatively (preferrably?), you may specify <class-cache> and <collection-cache> elements in hibernate.cfg.xml.

The usage attribute specifies a cache concurrency strategy.

19.2.2. Strategy: read only

If your application needs to read but never modify instances of a persistent class, a read-only cache may be used. This is the simplest and best performing strategy. It's even perfectly safe for use in a cluster.

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

19.2.3. Strategy: read/write

If the application needs to update data, a read-write cache might be appropriate. This cache strategy should never be used if serializable transaction isolation level is required. If the cache is used in a JTA environment, you must specify the property hibernate.transaction.manager_lookup_class, naming a strategy for obtaining the JTA TransactionManager. In other environments, you should ensure that the transaction is completed when Session.close() or Session.disconnect() is called. If you wish to use this strategy in a cluster, you should ensure that the underlying cache implementation supports locking. The built-in cache providers do not.

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

19.2.4. Strategy: nonstrict read/write

If the application only occasionally needs to update data (ie. if it is extremely unlikely that two transactions would try to update the same item simultaneously) and strict transaction isolation is not required, a nonstrict-read-write cache might be appropriate. If the cache is used in a JTA environment, you must specify hibernate.transaction.manager_lookup_class. In other environments, you should ensure that the transaction is completed when Session.close() or Session.disconnect() is called.

19.2.5. Strategy: transactional

The transactional cache strategy provides support for fully transactional cache providers such as JBoss TreeCache. Such a cache may only be used in a JTA environment and you must specify hibernate.transaction.manager_lookup_class.

None of the cache providers support all of the cache concurrency strategies. The following table shows which providers are compatible with which concurrency strategies.

Table 19.2. Cache Concurrency Strategy Support

Cache read-only nonstrict-read-write read-write transactional
Hashtable (not intended for production use) yes yes yes
EHCache yes yes yes
OSCache yes yes yes
SwarmCache yes yes
JBoss TreeCache yes yes

19.3. Managing the caches

Whenever you pass an object to save(), update() or saveOrUpdate() and whenever you retrieve an object using load(), get(), list(), iterate() or scroll(), that object is added to the internal cache of the Session.

When flush() is subsequently called, the state of that object will be synchronized with the database. If you do not want this synchronization to occur or if you are processing a huge number of objects and need to manage memory efficiently, the evict() method may be used to remove the object and its collections from the first-level cache.

ScrollableResult cats = sess.createQuery("from Cat as cat").scroll(); //a huge result set
while ( cats.next() ) {
     Cat cat = (Cat) cats.get(0);
     doSomethingWithACat(cat);
     sess.evict(cat);
}

The Session also provides a contains() method to determine if an instance belongs to the session cache.

To completely evict all objects from the session cache, call Session.clear()

For the second-level cache, there are methods defined on SessionFactory for evicting the cached state of an instance, entire class, collection instance or entire collection role.

sessionFactory.evict(Cat.class, catId); //evict a particular Cat
sessionFactory.evict(Cat.class);   //evict all Cats
sessionFactory.evictCollection("Cat.kittens", catId); //evict a particular collection of kittens
sessionFactory.evictCollection("Cat.kittens"); //evict all kitten collections

The CacheMode controls how a particular session interacts with the second-level cache.

  • CacheMode.NORMAL - read items from and write items to the second-level cache

  • CacheMode.GET - read items from the second-level cache, but don't write to the second-level cache except when updating data

  • CacheMode.PUT - write items to the second-level cache, but don't read from the second-level cache

  • CacheMode.REFRESH - write items to the second-level cache, but don't read from the second-level cache, bypass the effect of hibernate.cache.use_minimal_puts, forcing a refresh of the second-level cache for all items read from the database

To browse the contents of a second-level or query cache region, use the Statistics API:

Map cacheEntries = sessionFactory.getStatistics()
         .getSecondLevelCacheStatistics(regionName)
         .getEntries();

You'll need to enable statistics, and, optionally, force Hibernate to keep the cache entries in a more human-understandable format:

hibernate.generate_statistics true
hibernate.cache.use_structured_entries true

类别:默认分类 | 添加到搜藏 | 浏览() | 评论 (2)
 
最近读者:
 
网友评论:
1
2008-09-11 11:12
这根本不是你写的好发
 
2
2008-09-12 17:31
呵呵,本来就不是我写的。
 
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
验证码:
 

     

©2008 Baidu