Hibernate框架中的缓存技术详解
本文实例讲述了Hibernate框架中的缓存技术。分享给大家供大家参考,具体如下:
Hibernate框架的缓存分为Session的缓存、SessionFactory的缓存,也称为一级缓存和二级缓存。
一级缓存:
一级缓存是Session级的缓存,其生命周期很短,与Session相互对应,由Hibernate进行管理,属于事务范围的缓存。当程序调用Session的load()方法、get()方法、save()方法、saveOrUpdate()方法、update()方法或查询接口方法时,Hibernate会对实体对象进行缓存;当通过load()方法或get()方法查询实体对象时,Hibernate会首先到缓存中查询,在找不到实体对像的情况下,Hibernate才会发出SQL语句到数据库中查询,从而提高了Hibernate的使用效率。
举个例子来说吧:
packagecom.xqh.util; importorg.hibernate.Session; importcom.xqh.model.User; publicclassTest{ publicstaticvoidmain(String[]args){ Sessionsession=null; try{ session=HibernateUtil.getSession();//获取session session.beginTransaction();//开启事务 System.out.println("第一次查询:"); Useruser=(User)session.get(User.class,newInteger(1)); System.out.println("用户名:"+user.getName()); System.out.println("第二次查询:"); Useruser1=(User)session.get(User.class,1); System.out.println("用户名:"+user1.getName()); session.getTransaction().commit(); }catch(Exceptione){ e.printStackTrace(); //出错将回滚事务 session.getTransaction().rollback(); }finally{ //关闭Session对象 HibernateUtil.closeSession(session); } } }
当程序通过get()方法第一次查用户对象时,Hibernate会发出一条SQL语句进行查询,此时Hibernate对其用户对象进行了一级缓存;当再次通过get()方法查询时,Hibernate就不会发出SQL语句了,因为用户名已经存在于一级缓存中。程序运行结果:
第一次查询: Hibernate: select user0_.idasid0_0_, user0_.nameasname0_0_, user0_.sexassex0_0_ from tb_user_infouser0_ where user0_.id=? 用户名:xqh 第二次查询: 用户名:xqh
注意:一级缓存的生命周期与Session相对应,它并不会在Session之间共享,在不同的Session中不能得到其他Session中缓存的实体对象
二级缓存:
二级缓存是SessionFactory级的缓存,其生命周期与SessionFactory一致。二级缓存可在多个Session间共享,属于进程范围或群集范围的缓存。
二级缓存是一个可插拔的缓存插件,它的使用需要第三方缓存产品的支持。在Hibernate框架中,通过Hibernate配置文件配置二级缓存的使用策略。
1.加入缓存配置文件ehcache.xml
<ehcache> <!--Setsthepathtothedirectorywherecache.datafilesarecreated. IfthepathisaJavaSystemPropertyitisreplacedby itsvalueintherunningVM. Thefollowingpropertiesaretranslated: user.home-User'shomedirectory user.dir-User'scurrentworkingdirectory java.io.tmpdir-Defaulttempfilepath--> <diskStorepath="java.io.tmpdir"/> <!--DefaultCacheconfiguration.Thesewillappliedtocachesprogrammaticallycreatedthrough theCacheManager. ThefollowingattributesarerequiredfordefaultCache: maxInMemory-Setsthemaximumnumberofobjectsthatwillbecreatedinmemory eternal-Setswhetherelementsareeternal.Ifeternal,timeoutsareignoredandtheelement isneverexpired. timeToIdleSeconds-Setsthetimetoidleforanelementbeforeitexpires.Isonlyused iftheelementisnoteternal.Idletimeisnow-lastaccessedtime timeToLiveSeconds-Setsthetimetoliveforanelementbeforeitexpires.Isonlyused iftheelementisnoteternal.TTLisnow-creationtime overflowToDisk-Setswhetherelementscanoverflowtodiskwhenthein-memorycache hasreachedthemaxInMemorylimit. --> <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" /> <!--Predefinedcaches.Addyourcacheconfigurationsettingshere. IfyoudonothaveaconfigurationforyourcacheaWARNINGwillbeissuedwhenthe CacheManagerstarts ThefollowingattributesarerequiredfordefaultCache: name-Setsthenameofthecache.Thisisusedtoidentifythecache.Itmustbeunique. maxInMemory-Setsthemaximumnumberofobjectsthatwillbecreatedinmemory eternal-Setswhetherelementsareeternal.Ifeternal,timeoutsareignoredandtheelement isneverexpired. timeToIdleSeconds-Setsthetimetoidleforanelementbeforeitexpires.Isonlyused iftheelementisnoteternal.Idletimeisnow-lastaccessedtime timeToLiveSeconds-Setsthetimetoliveforanelementbeforeitexpires.Isonlyused iftheelementisnoteternal.TTLisnow-creationtime overflowToDisk-Setswhetherelementscanoverflowtodiskwhenthein-memorycache hasreachedthemaxInMemorylimit. --> <!--SamplecachenamedsampleCache1 Thiscachecontainsamaximuminmemoryof10000elements,andwillexpire anelementifitisidleformorethan5minutesandlivesformorethan 10minutes. Iftherearemorethan10000elementsitwilloverflowtothe diskcache,whichinthisconfigurationwillgotowhereverjava.io.tmpis definedonyoursystem.OnastandardLinuxsystemthiswillbe/tmp" --> <cachename="sampleCache1" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="300" timeToLiveSeconds="600" overflowToDisk="true" /> <!--SamplecachenamedsampleCache2 Thiscachecontains1000elements.Elementswillalwaysbeheldinmemory. Theyarenotexpired.--> <cachename="sampleCache2" maxElementsInMemory="1000" eternal="true" timeToIdleSeconds="0" timeToLiveSeconds="0" overflowToDisk="false" />--> <!--Placeconfigurationforyourcachesfollowing--> </ehcache>
2.设置Hibernate配置文件。
<!--开启二级缓存--> <propertyname="hibernate.cache.use_second_level_cache">true</property> <!--指定缓存产品提供商--> <propertyname="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property> <!--指定二级缓存应用到的实体对象--> <class-cacheclass="com.xqh.model.User"usage="read-only"></class-cache>
例:
packagecom.xqh.util; importorg.hibernate.Session; importcom.xqh.model.User; publicclassTest{ publicstaticvoidmain(String[]args){ Sessionsession=null;//第一个Session try{ session=HibernateUtil.getSession(); session.beginTransaction(); System.out.println("第一次查询:"); Useruser=(User)session.get(User.class,1); System.out.println("用户名:"+user.getName()); session.getTransaction().commit(); }catch(Exceptione){ e.printStackTrace(); //出错将回滚事务 session.getTransaction().rollback(); }finally{ //关闭Session对象 HibernateUtil.closeSession(session); } try{ session=HibernateUtil.getSession();//开启第二个缓存 session.beginTransaction(); System.out.println("第二次查询:"); Useruser=(User)session.get(User.class,1); System.out.println("用户名:"+user.getName()); session.getTransaction().commit(); }catch(Exceptione){ e.printStackTrace(); //出错将回滚事务 session.getTransaction().rollback(); }finally{ //关闭Session对象 HibernateUtil.closeSession(session); } } }
二级缓存在Session之间是共享的,因此可在不同Session中加载同一个对象,Hibernate将只发出一条SQL语句,当第二次加载对象时,Hibernate将从缓存中获取此对象。
程序结果:
第一次查询: Hibernate: select user0_.idasid0_0_, user0_.nameasname0_0_, user0_.sexassex0_0_ from tb_user_infouser0_ where user0_.id=? 用户名:xqh 第二次查询: 用户名:xqh
对于二级缓存,可以使用一些不经常更新的数据或参考的数据,此时其性能会得到明显的提升。但如果经常变化的数据应用二级缓存,则性能方面会造成一定问题。
希望本文所述对大家基于Hibernate框架的Java程序设计有所帮助。