Cache是~存Q它往往是提高系l性能的最重要手段Q对数据起到一个蓄水池和缓冲的作用。Cache对于大量依赖数据d操作的系l而言其重要。在大ƈ发量的情况下Q如果每ơ程序都需要向数据库直接做查询操作Q它们所带来的性能开销是显而易见的Q频J的|络舆,数据库磁盘的d操作都会大大降低pȝ的性能。此时如果能让数据库在本地内存中保留一个镜像,下次讉K的时候只需要从内存中直接获取,那么昄可以带来不小的性能提升。引入Cache机制的难Ҏ如何保证内存中数据的有效性,否则脏数据的出现会l系l带来难以预知的严重后果。虽然一个设计得很好的应用程序不用Cache也可以表现出让h接受的性能Q但毫无疑问Q一些对d操作要求比较高的应用E序可以通过Cache获得更高的性能。对于应用程序,Cache通过内存或磁盘保存了数据库中的当前有x据状态,它是一个存储在本地的数据备份。Cache位于数据库和应用E序之间Q从数据库更新数据,q给E序提供数据?br />
Hibernate实现了良好的Cache机制Q可以借助Hibernate内部的Cacheq速提高系l的数据d性能。Hibernate中的Cache可分Z层:一UCache和二UCache?br />
一UCache:
Session实现了第一UCacheQ它属于事务U数据缓册Ӏ一旦事务结束,q个Cache也随之失效。一个Session的生命周期对应一个数据库事务或一个程序事务?br />
Session-cache保证了一个Session中两ơ请求同一个对象时Q取得的对象是同一个JAVA实例Q有时它可以避免不必要的数据冲突。另外,它还能ؓ另一些重要的性能提供保证Q?br />
1Q在对一个对象进行自我@环引用时Q?不至于生堆栈溢出?br />
2Q当数据库事务结束时Q对于同一个数据库行,不会产生数据冲突Q因为对于数据库中的一行,最多只有一个对象来表示它?br />
3Q一个事务中可能会有很多个处理单元,在每一个处理单元中做的操作都会立即被另外的处理单元得知?br />
我们不用LL开Session-cacheQ它L被打开q且不能被关闭。当使用save(),update()或saveOrUpdate()来保存数据更改,或通过load(),find(),list(){方法来得到对象Ӟ对象׃被加入到Session-cache?br />
如果要同步很多数据对象,需要有效地理Cache,可以用Session的evict()Ҏ从一UCache中移除对象。如下:
Session session = HibernateUtil.currentSession();
Transaction tx = session.beginTransaction();
for(int i = 0 ; i <100000 ; i++)


{
Student stu = new Student();

session.save(stu);
}
tx.commit();
session.close();
在保?0000个或更多对象ӞE序可能会抛出OutOfMemoryException异常Q因为Hibernate在一UCache~存了新加入的所有对象。内存溢出。要解决q全问题需要把JDBC批处理数量设|ؓ一个合理的数|一般是10?0Q。在Hibernate的配|文件中可以加入以下属?br />
<property name="hibernate.jdbc.batch_size"> 20 </property>
然后我们在程序中一定时d提交q更新Session的Cache:
Session session = HibernateUtil.currentSession();
Transaction tx = session.beginTransaction();
for(int i = 0 ; i <100000 ; i++)


{
Student stu = new Student();

session.save(stu);
if(i%20 == 0) //每保存完20个对象后Q进行如下操?/span>

{
session.flush();//q个会提交更?/span>
session.clear();//清除Cache,释放内存
}
}
tx.commit();
session.close();
二Cache
二Cache是SessionFactory范围内的~存Q所有的Session׃n同一个二UCache。在二Cache中保存持久性实例的散装形式的数据。二UCache的内部如何实现ƈ不重要,重要的是采用哪种正确的缓存策略,以及采用哪个Cache提供器。持久化不同的数据需要不同的Cache{略Q比如一些因素将影响到Cache{略的选择Q数据的?写比例,数据表是否能被其他的应用E序扬访问等。对于一些读/写比例高的数据可以打开它的~存Q允许这些数据进入二U缓存容器有利于pȝ性能的优?而对于能被其它应用程序访问的数据对象Q最好将此对象的二Cache选项关闭?br />
讄Hibernate的二UCache需要分两步q行Q首先确认用什么数据ƈ发策略,然后配置~存q期旉q设|Cache提供器?br />
?U内|的Hibernate数据q发冲突{略Q代表数据库隔离U别Q如下:
1Q?span style="color: #0000ff">事务QTransactionQ?/span>仅在受管理的环境中可用。它保证可重ȝ事务隔离U别Q可以对?写比例高Q很更新的数据采用该策略?br />
2Q?span style="color: #0000ff">dQread-writeQ?/span>使用旉x制维护读写提交事务隔ȝ别。可以对?写比例高Q很更新的数据采用该策略?br />
3Q?span style="color: #0000ff">非严D写(notstrict-read-writeQ?/span>不保证Cache和数据库之间的数据库的一致性。用此{略Ӟ应该讄_的缓存过期时_否则可能从缓存中d脏数据。当一些数据极改变,q且当这些数据和数据库有一部䆾不量影响不大Ӟ可以使用此策略?br />
4Q?span style="color: #0000ff">只读Qread-onlyQ?/span>当确保数据永不改变时Q可以用此{略?/p>
我们定了Cache{略后,p挑选一个高效的Cache提供器,它将作ؓ插g被Hibernate调用。Hibernate允许使用下述几种~存插gQ?br />
EhCacheQ可以在JVM中作Z个简单进E范围内的缓存,它可以把~存的数据放入内存或盘Qƈ支持Hibernate中可选用的查询缓存?br />
OpenSymphony OSCacheQ和EhCache怼Qƈ且提供了丰富的缓存过期策略?br />
SwarmCacheQ可作ؓ集群范围的缓存,但不支持查询~存?br />
JBossCacheQ可作ؓ集群范围的缓Ԍ但不支持查询~存?/p>
在Hibernate中用EhCache
EhCache是一个纯JAVAE序Q可以在Hibernate中作Z个插件引入。在Hibernate中用EhCache需要在Hibernate的配|文件中讄如下Q?/p>
<propery name="hibernate.cache.provider_class">
org.hibernate.cache.EhCacheProvider
</property>
EhCacheProvidercL位于Hibernate3.jar包中而不是ehcache-1.1.jar包中。EhCache有自q配置文Q名为chcache.xml。Hibernate3.x中的etc目录下有ehcache.xml的示例文Ӟ只须要将 它COPY到我们的应用E序src目录下(~译时会把ehcache.xmlCOPY到WEB-INF/classes目录下)。对其中的相兛_D行更改以和自qE序盔R应。进行配|后Q在ehcache.xml文g中的代码如下Q?
<ehcache>
<diskStore path="c:\\cache"/> //讄cache.data文g存放位置

<defaultCache
maxElementsInMemory="10000" //~存中允许创建的最大对象数
eternal="false" //~存中对象是否ؓ怹?br />
timeToIdleSeconds="120"//~存数据钝化旉(卛_象在它过期前的空闲时?
timeToLiveSeconds="120"//~存数据生存旉(卛_象在它过期前的生存时?
overflowToDisk="true"
/>
<cache name="Student" //用户自定义的Cache配置
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
/>
</ehcache>
此外我们q需要在持久化类的映文件中q行配置。例如,Group(班)和Student(学生)是一对多的关p,它们对应的数据表分别是t_group和t_student。现在要把Studentcȝ数据q行二~存Q这需要在二个映射文g中都对二U缓存进行配|?br />
在Group.hbm.xml中如?br />
在其<set></set>中添?
<cache usage="read-write"/><!--集合中的数据被缓?/span>-->
上述文g虽然?lt;set>标记中设|了<cache usage="read-write"/>Q?span style="color: #0000ff">但Hibernate只是把Group相关的Student的主键ID加入到缓存中Q如果希望把整个Student的散装属性都加入CU缓存中Q还需要在Student.hbm.xml文g?lt;class>标记中添?lt;cache>子标?/span>。如下:
<class name="Student" table="t_student">
<cache usage="read-write" /><!--cache标记需跟在class标记?/span>-->
</class>

]]>