本文主要是介绍Hibernate 一级缓存和二级缓存,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
一级缓存[Session级别]
一个Session做了一个查询操作,它会把这个操作的结果放在一级缓存中,如果短时间内这个session(一定要同一个session)又做了同一个操作,那么hibernate直接从一级缓存中拿,而不会再去连数据库,取数据
每个事务都有单独的第一级缓存进程范围或集群范围
缓存被同一个进程或集群范围内的所有事务共享并发访问策略由于每个事务都拥有单独的第一级缓存,不会出现并发问题
处于一级缓存中的对象永远不会过期
除非应用程序显式清空缓存或者清除特定的对象,必须提供数据过期策略,如基于内存的缓存中的对象的最大数目,允许对象处于缓存中的最长时间,以及允许对象处于缓存中的最长空闲时间物理存储介质内存内存和硬盘。
对象的散装数据首先存放在基于内存的缓存中,当内存中对象的数目达到数据过期策略中指定上限时,就会把其余的对象写入基于硬盘的缓存中。
save、update、saveOrupdate、load、list、iterate、lock会向一级缓存存放数据
Session为应用程序提供了两个管理缓存的方法:
evict(Object obj):从缓存中清除参数指定的持久化对象。 clear():清空缓存中所有持久化对象。
query.list()和query.iterate()
query.list()会一次性查询出所有的对象并且放入一级缓存中
@Testpublic void testQueryList() throws Exception {Session session = HibernateUtils.getSession();Query query = session.createQuery("from Student");//把查询出的所有学生信息放入一级缓存List<Student> list = (List<Student>) query.list();//此时再查询会直接从一级缓存中取Student student = session.get(Student.class,0);}
输出结果
Hibernate:
selectstudent0_.id as id1_0_,student0_.phone as phone2_0_,student0_.postcode as postcode3_0_,student0_.birth as birth4_0_,student0_.c_id as c_id7_0_,student0_.gender as gender5_0_,student0_.name as name6_0_
fromstudent student0_
Hibernate: selectclasses0_.c_id as c_id1_1_0_,classes0_.c_name as c_name2_1_0_ fromclass classes0_ whereclasses0_.c_id=?
query.iterate()会查询出所有对象的id 当要获取某个对象时再去数据库中取
@Testpublic void testIterate() throws Exception {Session session = HibernateUtils.getSession();Query query = session.createQuery("from Student ");//查询出所有student的idIterator<Student> iterate = query.iterate();//当要获取某个student对象时 再去数据库取while (iterate.hasNext()){System.out.println(iterate.next());}}
输出结果
Hibernate:
selectstudent0_.id as col_0_0_
fromstudent student0_
Hibernate: selectstudent0_.id as id1_0_0_,student0_.phone as phone2_0_0_,student0_.postcode as postcode3_0_0_,student0_.birth as birth4_0_0_,student0_.c_id as c_id7_0_0_,student0_.gender as gender5_0_0_,student0_.name as name6_0_0_,classes1_.c_id as c_id1_1_1_,classes1_.c_name as c_name2_1_1_ fromstudent student0_ left outer joinclass classes1_ on student0_.c_id=classes1_.c_id wherestudent0_.id=?
Student{id=0, name='heqianqian', gender='female', birth=2017-04-30, address=Address{postCode='335400', phone='10086'}
如果我们需要在一个session当中要两次查询出很多对象,可以第一次使用List将对象信息放入一级缓存,第二次使用iterate获取所有对象的id 再根据id去一级缓存中获取数据
注意:
① 一级缓存不需要配置,就可以使用,它本身没有保护机制,所以我们程序员要考虑这个问题,我们可以同 evict 或者 clear来清除session缓存中对象. evict 是清除一个对象,clear是清除所有的sesion缓存对象
② session级缓存中对象的生命周期, 当session关闭后,就自动销毁.
二级缓存[SessionFactory级别]
使用hibernate二级缓存,我们首先需要对其进行配置,配置步骤如下:
1.添加jar包
hibernate并没有提供相应的二级缓存的组件,常用的二级缓存包是EHcache
<!--cache--><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-ehcache</artifactId><version>5.2.10.Final</version></dependency><dependency><groupId>net.sf.ehcache</groupId><artifactId>ehcache</artifactId><version>2.10.2</version></dependency><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version></dependency>
2.在hibernate配置文件中开启二级缓存总开关 并且配置ehcache配置文件的位置
<!-- 开启二级缓存 --><property name="hibernate.cache.use_second_level_cache">true</property><!-- 二级缓存的提供类 在hibernate4.0版本以后我们都是配置这个属性来指定二级缓存的提供类--><property name="hibernate.cache.region.factory_class">org.hibernate.cache.SingletonEhCacheRegionFactory</property><!-- 二级缓存配置文件的位置 --><property name="hibernate.cache.provider_configuration_file_resource_path">ehcache.xml</property><!--如果是使用hibernate3的版本的话,那么二级缓存的提供类则要配置成这个:--><property name="hibernate.cache.provider_class">net.sf.ehcache.hibernate.EhCacheProvider</property>
3.在ehcache.xml中配置缓存信息
<ehcache><!--指定数据在磁盘中的存储位置--><diskStore path="F:\ehcache"/><!--当借助CacheManager.add("demoCache")创建Cache时,EhCache便会采用<defalutCache/>指定的的管理策略--><defaultCache
maxElementsInMemory="1000"maxElementsOnDisk="10000000"eternal="false"overflowToDisk="false"timeToIdleSeconds="120"timeToLiveSeconds="120"diskExpiryThreadIntervalSeconds="120"memoryStoreEvictionPolicy="LRU"><!--必选参数1.maxElementsInMemory:在内存中缓存的element的最大数目2.maxElementsOnDisk:在磁盘上缓存的element的最大数目,若是0表示无穷大3.eternal:设定缓存的elements是否永远不过期如果为true,则缓存的数据始终有效如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断4.overflowToDisk:设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上--><!--可选参数1.timeToIdleSeconds:当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大2.timeToLiveSeconds:缓存element的有效生命期,默认是0.,也就是element存活时间无穷大3.diskSpoolBufferSizeMB:设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每个Cache都应该有自己的一个缓冲区4.diskPersistent:在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false5.diskExpiryThreadIntervalSeconds:磁盘缓存的清理线程运行间隔,默认是120秒。每个120s,相应的线程会进行一次EhCache中数据的清理工作6.memoryStoreEvictionPolicy:当内存缓存达到最大,有新的element加入的时候,移除缓存中element的策略。默认是LRU(最近最少使用)可选的有LFU(最不常使用)和FIFO(先进先出)-->
</defaultCache>
</ehcache>
4.开启二级缓存
1)使用xml方式
<class name="com.hqq.bean.Student" table="student" schema="hibernate"><!--二级缓存一般设置为只读的 --><cache usage="read-only"/><id name="id" column="id"/><property name="name" column="name"/><property name="gender" column="gender"/><property name="birth" column="birth"/><!--<property name="address" column="address"/>--><component name="address" class="com.hqq.bean.Address"><property name="phone" column="phone"/><property name="postCode" column="postcode"/></component></class>
二级缓存的使用策略一般有这几种:read-only、nonstrict-read-write、read-write、transactional
2)使用注解的方式
@Entity
@Table(name = "student", schema = "hibernate")
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)//表示开启二级缓存,并使用read-only策略
public class Student implements Serializable {
5.配置完毕 测试二级缓存是否开启
@Testpublic void test() throws Exception {Session session = HibernateUtils.getSession();Student student = session.get(Student.class, 0);System.out.println(student);session.close();Session session2 = HibernateUtils.getSession();Student student2 = session2.get(Student.class, 0);System.out.println(student2);}
测试结果
Hibernate:
selectclasses0_.c_id as c_id1_1_0_,classes0_.c_name as c_name2_1_0_
fromclass classes0_
whereclasses0_.c_id=?Student{id=0, name='heqianqian', gender='female', birth=2017-04-30, address=Address{postCode='335400', phone='10086'}
注意:
- 二级缓存缓存的是对象 不会缓存属性
- 二级缓存不会缓存hql语句 需要配置:
hibernate.cfg.xml
<!-- 开启查询缓存 --><property name="hibernate.cache.use_query_cache">true</property>
Student类上添加@Cachable注解
@Entity
@Table(name = "student", schema = "hibernate")
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)//表示开启二级缓存,并使用read-only策略
public class Student implements Serializable {
测试
@Testpublic void testHql() throws Exception {Session session = HibernateUtils.getSession();List<Student> list = session.createQuery("from Student ").setCacheable(true).list();Iterator<Student> students = (Iterator<Student>) list.iterator();while (students.hasNext()){System.out.println(students.next());}//session.close();Session session1 = HibernateUtils.getSession();List<Student> list1 = session.createQuery("from Student ").setCacheable(true).list();Iterator<Student> students1 = (Iterator<Student>) list1.iterator();while (students1.hasNext()){System.out.println(students1.next());}}
输出:
Hibernate:
selectstudent0_.id as id1_0_,student0_.phone as phone2_0_,student0_.postcode as postcode3_0_,student0_.birth as birth4_0_,student0_.c_id as c_id7_0_,student0_.gender as gender5_0_,student0_.name as name6_0_
fromstudent student0_
Hibernate: selectclasses0_.c_id as c_id1_1_0_,classes0_.c_name as c_name2_1_0_ fromclass classes0_ whereclasses0_.c_id=?Student{id=0, name='heqianqian', gender='female', birth=2017-04-30, address=Address{postCode='335400', phone='10086'}Student{id=0, name='heqianqian', gender='female', birth=2017-04-30, address=Address{postCode='335400', phone='10086'}
参考文章:
http://www.cnblogs.com/xiaoluo501395377/p/3377604.html
http://blog.csdn.net/xlgen157387/article/details/40071651
这篇关于Hibernate 一级缓存和二级缓存的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!