ITEEDU

Hibernate Gossip: 二级快取(Second-level)

Hibernate的 Session level 快取 随着Session生命周期起始与消灭。

第一个 Hibernate 中的范例来说,在未使用二级快取的情况下,如果使用以下的程序片段来查询数据:
Session session = sessionFactory.openSession();
User user1 = (User) session.load(User.class, new Integer(1));       
user1.getName();       
session.close();       
      
session = sessionFactory.openSession();       
User user2 = (User) session.load(User.class, new Integer(1));       
user2.getName();       
session.close(); 
则Hibernate将会使用以下的SQL来进行数据查询:
Hibernate: select user0_.id as id0_, user0_.name as name0_0_, user0_.age as age0_0_ from user user0_ where user0_.id=?
Hibernate: select user0_.id as id0_, user0_.name as name0_0_, user0_.age as age0_0_ from user user0_ where user0_.id=? 
由于Session被关闭,Session level无法起作用,所以第二次的查询仍必须向数据库直接查询。

Hibernate二级快取可以跨越数个Session,二级快取由同一个SessionFactory所建立的Session所共享,因而又称为SessionFactory level快取。

Hibernate本身并未提供二级快取的实现,而是藉由第三方(Third-party)产品来实现,Hibernate预设使用EHCache作为其 二级快取的实现,在最简单的情况下,您只需在Hibernate下撰写一个ehcache.xml作为EHCache的资源定义档,可以在 Hibernate下载档案中的etc目录下找到一个已经撰写好的ehcache.xml,以下撰写最简单的ehcache.xml:
ehcache.xml
<ehcache>
<diskStore path="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
</ehcache>
将这个档案放在Hibernate项目Classpath可存取到的路径下,接着重新运行上面的程序片段,您可以发现Hibernate将使用以下的SQL进行查询:
Hibernate: select user0_.id as id0_, user0_.name as name0_0_, user0_.age as age0_0_ from user user0_ where user0_.id=?
二级快取被同一个SessionFactory所建立的Session实例所共享,所以即使关闭了Session,下一个Session仍可使用二级快 取,在查询时,Session会先在Session level快取中查询看有无数据,如果没有就试着从二级快取中查询数据,查到数据的话就直接返回该笔数据,所以在上例中,第二次无需再向数据库进行SQL查询。

如果打算清除二级快取的资料,可以使用SessionFactory的evict()方法,例如:
sessionFactory.evict(User.class, user.getId());
如果打算在Hibernate中使用其它第三方产品进行快取,则可以在hibernate.cfg.xml中定义hibernate.cache.provider_class属性,例如:
hibernate.cfg.xml
<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

<session-factory>

....
<property name="hibernate.cache.provider_class">
org.hibernate.cache.HashtableCacheProvider
</property>
....

</session-factory>

</hibernate-configuration>
HashtableCache是Hibernate自己所提供的二级快取实现,不过性能与功能上有限,只用于开发时期的测试之用。

可以在映射文件中指定快取策略,使用<cache>卷标在映像实体或Collection上设定快取策略,例如:
User.hbm.xml
<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

<class name="onlyfun.caterpillar.User" table="user">
<cache usage="read-only"/>

<id name="id" column="id" type="java.lang.Integer">
<generator class="native"/>
</id>

<property name="name" column="name" type="java.lang.String"/>

<property name="age" column="age" type="java.lang.Integer"/>

</class>

</hibernate-mapping>
可以设定的策略包括read-only、read-write、nonstrict-read-write与transactional,并不是每一个第三方快取实现都支持所有的选项,每一个选项的使用时机与支持的产品,可以直接参考Hibernate官方参考手册的 20.2. The Second Level Cache