`
zyongking
  • 浏览: 57364 次
  • 性别: Icon_minigender_1
  • 来自: 湖北
社区版块
存档分类
最新评论

hibernate二级缓存

阅读更多

Hibernate二级缓存技术

大量数据流动是web应用性能问题常见的原因,而缓存被广泛的用于优化数据库应用。cache被设计为通过保存从数据库里load的数据来减少应用和数据 库之间的数据流动。数据库访问只有当检索的数据不在cache里可用时才必要。hibernate可以用两种不同的对象缓存:first-level cache 和 second-level cache。first-level cache和Session对象关联,而second-level cache是和Session Factory对象关联。 

    缺省地,hibernate已经使用基于每个事务的first-level cache。 Hibernate用first-level cache主要是减少在一个事务内的sql查询数量。例如,如果一个对象在同一个事务内被修改多次,hibernate将只生成一个包括所有修改的 UPDATE SQL语句。为了减少数据流动,second-level cache在Session Factory级的不同事务之间保持load的对象,这些对象对整个应用可用,不只是对当前用户正在运行的查询。这样,每次查询将返回已经load在缓存 里的对象,避免一个或更多潜在的数据库事务。

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

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

1、 在此我们采用ehcache来实现,下载地址:http://ehcache.sourceforge.net/  hibernate3.2必须要ehcache1.2以上才能支持。可以修改log4j配置文件log4j.logger.net.sf.hibernate.cache=debug查看日志

将包添加到工程。

2、编写 ehcache.xml文件放在src文件夹下

<?xml version="1.0" encoding="UTF-8"?>

<ehcache>

 <diskStore path="java.io.tmpdir"/> 

  <defaultCache

   maxElementsInMemory="10000" <!-- 缓存最大数目 -->

   eternal="false" <!-- 缓存是否持久 -->

   overflowToDisk="true" <!-- 是否保存到磁盘,当系统当机时-->

   timeToIdleSeconds="300" <!-- 当缓存闲置n秒后销毁 -->

   timeToLiveSeconds="180" <!-- 当缓存存活n秒后销毁-->

   diskPersistent="false"

   diskExpiryThreadIntervalSeconds= "120"/> 

</ehcache>

3、 如果是spring管理session的话:

<bean id="mysessionFactory"

class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

<property name="dataSource">

<ref bean="conn" />

</property>

<property name="hibernateProperties">

<props>

<prop key="hibernate.dialect">

org.hibernate.dialect.SQLServerDialect

</prop>

<prop key="hibernate.show_sql">true</prop>

<prop key="hibernate.cache.use_query_cache">true</prop>

<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider

</prop>

</props>

</property>

<property name="mappingResources">

<list>

<value>com/po/Admin.hbm.xml</value>

</list>

</property>

</bean>

 

说明:如果不设置查询缓存,那么hibernate只会缓存使用load()方法获得的单个持久化对象,如果想缓存使用findall()、 list()Iterator()createCriteria()createQuery()等方法获得的数据结果集的话,就需要设置 hibernate.cache.use_query_cache true 才行

4、修改Mapping文件。

    <cache usage="read-only"/>

5、 如果需要“查询缓存”,还需要在使用Query或Criteria()时设置其setCacheable(true);属性

6、 测试:

public static void main(String[] args) {

// TODO Auto-generated method stub

ApplicationContext actx = new FileSystemXmlApplicationContext("WebRoot\\WEB-INF\\applicationContext.xml");

AdminDAO dao = (AdminDAO) actx.getBean("AdminDAO");

System.out.println("第一次查询开始");

for(int i=0;i<dao.findAll().size();i++){

Admin admin = (Admin) dao.findAll().get(i);

System.out.println(admin.getUsername()+"**********************"); 


}


System.out.println("开始休眠");

try {

Thread.sleep(11133);

} catch (Exception e){

System.out.print("error................");

System.out.print(e.getMessage());

}

System.out.println("第二次查询开始");

for(int i=0;i<dao.findAll().size();i++){

Admin admin = (Admin) dao.findAll().get(i);

System.out.println(admin.getUsername()+"*************************"); 


}

System.out.print("END....");

}

 

7、结束语:

无论何时,当你给save()update()或 saveOrUpdate()方法传递一个对象时,或使用load()、 get()list()iterate() 或scroll()方法获得一个对象时, 该对象都将被加入到Session的内部缓存中。 当随后flush()方法被调用时,对象的状态会和数据库取得同步。 如果你不希望此同步操作发生,或者你正处理大量对象、需要对有效管理内存时,你可以调用evict() 方法,从一级缓存中去掉这些对象及其集合。 如下:

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);

}

Session还提供了一个contains()方法,用来判断某个实例是否处于当前session的缓存中。 如若要把所有的对象从session缓存中彻底清除,则需要调用Session.clear()

绝大多数的查询并不能从查询缓存中受益,所以Hibernate默认是不进行查询缓存的。如若需要进行缓存,请调用 Query.setCacheable(true)方法。这个调用会让查询在执行过程中时先从缓存中查找结果, 并将自己的结果集放到缓存中去。 

如果你要对查询缓存的失效政策进行精确的控制,你必须调用Query.setCacheRegion()方法, 为每个查询指定其命名的缓存区域。 

List blogs = sess.createQuery("from Blog blog where blog.blogger = :blogger")
    .setEntity("blogger", blogger)
    .setMaxResults(15)
    .setCacheable(true)
    .setCacheRegion("frontpages")
    .list();

如果查询需要强行刷新其查询缓存区域,那么你应该调用Query.setCacheMode(CacheMode.REFRESH)方法。 这对在其他进程中修改底层数据(例如,不通过Hibernate修改数据),或对那些需要选择性更新特定查询结果集的情况特别有用。 这是对SessionFactory.evictQueries()的更为有效的替代方案,同样可以清除查询缓存区域。

<!--EndFragment-->
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics