《使用Hibernate缓存数据.ppt》由会员分享,可在线阅读,更多相关《使用Hibernate缓存数据.ppt(16页珍藏版)》请在三一办公上搜索。
1、第15章 使用Hibernate缓存数据,目 录,1,2,缓存的概念和范围,一级缓存,2,3,4,二级缓存,查询缓存,15.1,缓存的概念和范围,3,15.1 缓存的概念和范围,4,缓存的介质一般是内存,所以读写速度很快。但如果缓存中存放的数据量非常大时,也会用硬盘作为缓存介质。缓存的实现不仅仅要考虑存储的介质,还要考虑到管理缓存的并发访问和缓存数据的生命周期。Hibernate的缓存包括Session的缓存和SessionFactory的缓存,其中SessionFactory的缓存又可以分为两类:内置缓存和外置缓存。Session的缓存是内置的,不能被卸载,也被称为Hibernate的第一级
2、缓存。SessionFactory的缓存又被称为Hibernate二级缓存。Hibernate缓存的范围包括事务范围、进程范围和集群范围,具体如下:(1)事务范围:(2)进程范围:(3)集群范围:,Hibernate提供的一级缓存是一个线程对应一个session,一个线程可以看成一个用户。也就是说session级缓存(一级缓存)只能给一个线程用,别的线程用不了,一级缓存就是和线程绑定了。Hibernate一级缓存生命周期很短,和session生命周期一样,一级缓存也称session级的缓存或事务级缓存。如果事务提交或回滚了,我们称session就关闭了,生命周期结束了。Hibernate二级缓
3、存需要sessionFactory来管理,它是进初级的缓存,所有人都可以使用,它是共享的。使用缓存,肯定是长时间不改变的数据,如果经常变化的数据放到缓存里就没有太大意义了。因为经常变化,还是需要经常到数据库里查询,那就没有必要用缓存了。,(1)事务范围:缓存只能被当前事务访问。缓存的生命周期依赖于事务的生命周期,当事务结束时,缓存也就结束生命周期。在此范围下,缓存的介质是内存。(2)进程范围:缓存被进程内的所有事务共享。这些事务有可能是并发访问缓存,因此必须对缓存采取必要的事务隔离机制。(3)集群范围:在集群环境中,缓存被一个机器或者多个机器的进程共享。缓存中的数据被复制到集群环境中的每个进程
4、节点,进程间通过远程通信来保证缓存中的数据一致性,缓存中的数据通常采用对象的松散数据形式。,15.2,一级缓存,5,15.2 一级缓存,6,Hibernate的一级缓存由Session提供,只存在于Session的生命周期中。当应用程序调用Session接口的save()、update()、saveOrUpdate()、get()、load()或者Query和Criteria实例的list()、iterate()等方法时,如果Session缓存中没有相应对象,Hibernate就会把对象加入到一级缓存中。当Session关闭时,该Session所管理的一级缓存也会立即被清除。1一个sessio
5、n中发出两次get查询 将项目hibernate-10复制并命名为“hibernate-11”,再导入到MyEclipse开发环境中。在项目hibernate-10的测试类HibernateTest中添加testSessionCache_1()方法,并使用Test注解加以修饰,在同一个session中发出两次get查询。,Test public void testSessionCache_1()User u1=(User)session.get(User.class,1);System.out.println(用户名:+u1.getLoginName();User u2=(User)sessi
6、on.get(User.class,1);System.out.println(用户名:+u2.getLoginName();,15.2 一级缓存,7,2开启两个session中发出两次get查询 在测试类HibernateTest中添加testSessionCache_2()方法,并使用Test注解加以修饰,开启两个session中发出两次get查询。,Test public void testSessionCache_2()User u1=(User)session.get(User.class,1);System.out.println(用户名:+u1.getLoginName();mi
7、t();session.close();session=sessionFactory.openSession();transaction=session.beginTransaction();User u2=(User)session.get(User.class,1);System.out.println(用户名:+u2.getLoginName();,15.2 一级缓存,8,3在一个Session中先save,再执行load查询 在测试类HibernateTest中添加testSessionCache_3()方法,并使用Test注解加以修饰,在一个session中先执行save操作,再执行
8、load查询。Session接口为应用程序提供了两个管理缓存的方法:evict()方法和clear()方法。其中evict()方法用于将某个对象从Session的一级缓存中清除;clear()方法用于将一级缓存中的所有对象全部清除。在测试类HibernateTest中添加testSessionCacheClear()方法,并使用Test注解加以修饰,在同一个Session中先调用load查询,然后执行clear()方法,最后再调用load查询。,Test public void testSessionCache_3()User user=new User(NewUser,123456,新用户)
9、;Serializable id=session.save(user);User u=(User)session.get(User.class,id);System.out.println(用户名:+u.getLoginName();,Test public void testSessionCacheClear()User u1=(User)session.get(User.class,1);System.out.println(用户名:+u1.getLoginName();User u2=(User)session.get(User.class,1);session.clear();Syst
10、em.out.println(用户名:+u2.getLoginName();,15.3,二级缓存,9,15.3 二级缓存,10,二级缓存是一个可插拔的缓存插件,它是由SessionFactory负责管理。由于SessionFactory对象的生命周期和应用程序的整个过程对应,因此二级缓存是进程范围或者集群范围的缓存。与一级缓存一样,二级缓存也根据对象的ID来加载缓存。当执行某个查询获得的结果集为实体对象集时,Hibernate就会把它们按照对象ID加载到二级缓存中。在访问指定ID的对象时,首先从一级缓存查找,找到直接使用,找不到转到二级缓存查找(必须配置且启用二级缓存)。如果二级缓存中找到,则
11、直接使用,否则会查询数据库,并将查询结果根据对象的Id放到缓存中。1常用的二级缓存插件 Hibernate的二级缓存功能是通过配置二级缓存插件来实现的,常用的二级缓存插件包括EHCache、OSCache、SwarmCache和JBossCache。,15.3 二级缓存,11,2Hibernate使用EHCache的步骤(1)引入EHCache相关的jar包 引入hibernate-release-5.2.6.Finalliboptionalehcache目录下的、三个jar包。(2)创建EHCache的配置文件ehcache.xml 可直接拷贝hibernate-release-5.2.6.
12、Finalprojectetc ehcache.xml拷贝到项目hibernate-11的src目录下。(3)在Hibernate配置文件里面启用EHCache 在配置文件中,启用EHCache。(4)配置哪些实体类的对象需要二级缓存 在实体类的映射文件中配置并发访问策略 在Hibernate配置文件中统一配置(推荐使用),true,元素的后面-,15.3 二级缓存,12,3实体对象级别的二级缓存测试 二级缓存配置好后,再次执行测试类HibernateTest中的testSessionCache_2()方法,看执行结果。4使用collection-cache配置集合级别的二级缓存 在测试类Hi
13、bernateTest中添加testSecondCache()方法,并使用Test注解加以修饰,查看执行结果。在文件中使用元素来配置Mealseries类的对象的二级缓存,再执行testSecondCache()方法,查看执行结果。在文件中使用元素来配置集合mealSet的二级缓存,再执行testSecondCache()方法,查看执行结果。在文件中元素来配置Meal类的对象的二级缓存,再执行testSecondCache()方法,查看执行结果。,控制台输出结果:Hibernate:select from restrant.users user0_ where user0_.Id=?用户名:z
14、hangsan用户名:zhangsan 第一次执行get方法查询出结果后,关闭了session,一级缓存被清除了,由于配置并启用了二级缓存,查询出的结果会放入二级缓存。第二次执行get方法时,首先从一级缓存中查找,没有找到;然后转到二级缓存查找,二级缓存中找到结果,不需要从数据库查询。,Testpublic void testSecondCache()Mealseries ms1=(Mealseries)session.get(Mealseries.class,1);System.out.println(菜系:+ms1.getSeriesName();System.out.println(数量
15、:+ms1.getMealSet().size();mit();session.close();session=sessionFactory.openSession();transaction=session.beginTransaction();Mealseries ms2=(Mealseries)session.get(Mealseries.class,1);System.out.println(菜系:+ms2.getSeriesName();System.out.println(数量:+ms2.getMealSet().size();,Hibernate:菜系:鲁菜Hibernate:数
16、量:9Hibernate:菜系:鲁菜Hibernate:数量:9 第一次执行get方法加载SeriesId=1的Mealseries对象ms1时发出第一条SQL语句;执行ms1.getMealSet()时发出第二条SQL语句,之后关闭session,一级缓存被清除了。由于此时没有针对Mealseries类配置二级缓存,因此第二次加载SeriesId=1的Mealseries对象ms2,执行ms2.getMealSet()时会发出第三、第四条SQL语句重新获取数据。,Hibernate:菜系:鲁菜Hibernate:数量:9菜系:鲁菜Hibernate:数量:9 由于针对Mealseries类的
17、对象配置了二级缓存,关闭session后,第二次加载SeriesId=1的Mealseries对象ms2时,可以从二级缓存中获取,因此少发出一条SQL语句。但是在执行ms2.getMealSet()时还是会发出SQL语句重新获取数据,这是因为Mealseries对象中Meal类型的集合mealSet没有配置二级缓存。,15.3 二级缓存,13,5基于硬盘的二级缓存 在配置文件ehcache.xml中,首先修改元素配置,指定EHCache把数据写入磁盘时的目录(非系统盘)。修改ehcache.xml中原先的命名缓存区域sampleCache1和sampleCache2,为每个缓存区域设置不同的缓
18、存策略。给测试类HibernateTest中用After注解修饰的destroy()方法中的“sessionFactory.close();”语句添加断点,选中testSecondCache()方法,点右键选择“Debug As 1 JUnit Test”,以调试的方式执行测试类中的testSecondCache()方法。当程序暂停在“sessionFactory.close();”语句时,打开“E:EHCache”,可以看到缓存到磁盘的实体类对象文件。程序执行结束后,sessionFactory关闭了,缓存到磁盘的文件就会自动被删除。,15.4,查询缓存,14,15.4 查询缓存,15,对经
19、常使用的查询语句,如果启用了查询缓存,当第一次执行查询语句时,Hibernate会将查询结果存储在第二级缓存中。再次查询时,从缓存中获取查询结果,提高性能。Hibernate的查询缓存主要是针对普通属性结果集的缓存,而对于实体对象的结果集只缓存ID。如果当前关联的表发生修改,则查询缓存生命周期结束。在测试类HibernateTest中添加testQueryCache()方法,并使用Test注解加以修饰,代码如下:默认情况下,设置的缓存对HQL和QBC查询是无效的。查询缓存基于二级缓存,使用查询缓存前,必须首先配置二级缓存。在配置了二级缓存基础上,在Hibernate的配置文件中添加如下配置,可
20、以启用查询缓存。此外,还需在testQueryCache()方法中调用Query或Criteria的setCacheable(true)方法。再次执行方法。,Test public void testQueryCache()Query query=session.createQuery(From User);List us=query.getResultList();System.out.println(用户数:+us.size();us=query.getResultList();(用户数:+us.size();,true,Test public void testQueryCache()Query query=session.createQuery(From User);query.setCacheable(true);,总结,16,本章主要讲解了缓存的概念和范围,一级缓存、二级缓存,查询缓存等,并通过具体方法示例进行验证,让读者进一步加深了对Hibernate框架的了解。,