




下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、关于 hibernate 缓存基本的缓存原理Hibernate 缓存分为二级,第一级存放于 ses中称为一级缓存,默认带有且不能卸载。第二级是由 sesFactory 控制的进程级缓存。是全局共享的缓存,凡是会调用二级缓存的查询方法都会从中受益。只有经正确的配置后二级缓存才会发挥作用。同时在进行条件查询时必须使用相应的方法才能从缓存中获取数据。比如 Query.iterate()方法、load、get 方法等。必须注意的是 ses.find 方法是从数据库中获取数据,不会从二级缓存中获取数据,即便其中有其所需要的数据也是如此。查询时使用缓存的实现过程为:首先查询一级缓存中是否具有需要的数据,如
2、果没有,查询二级缓存,如果二级缓存中也没有,此时再执行查询数据库的工作。要注意的是:此 3 种方式的查询速度是依次降低的。存在一级缓存以及使用二级缓存的原因:因为 Ses的生命期往往很短,存在于 Ses的第一级最快缓存的生命期当然也很短,所以第一级缓存中率是很低的。其对系统性能的改善也是很有限的。当然,这个缓存的主要作用是保持 Ses数据状态同步。并非是 hibernate 为了大幅Ses提高系统性能所提供的。为了提高使用 hibernate 的性能,除了常规的一些需要注意的方法比如:使用延迟加载、迫切外连接、查询过滤等以外,还需要配置 hibernate 的二级缓存。其对系统整体性能的改善往
3、往具有立竿见影的效果!Hibernate 所有缓存机制详解 hibernate 提供的一级缓存 hibernate 是一个线程对应一个 ses,一个线程可以看成一个用户。也就是说 ses级缓存(一级缓存)只能给一个线程用,别的线程用不了,一级缓存就是和线程绑定了。hibernate 一级缓存生命周期很短,和 ses生命周期一样,一级缓存也称 ses级的缓存或事务级缓存。如果 tb 事务提交或回滚了,称 ses就关闭了,生命周期结束了。缓存和连接池的区别:缓存和池都是放在内存里,实现是一样的,都是为了提高性能的。但有细微的差别,池是重量级的,里面的数据是一样的,比如一个池里放 100 个 Con
4、nection连接对象,这个 100 个都是一样的。缓存里的数据,每个都不一样。比如100 条数据库放到缓存里,这 100 条缓存主要是用于查询都不一样。/同一个 ses中,发出两次 load 方法查询Student student = (Student)ses.load(Student.class, 1);System.out.prln(= + student.getName();/不会发出查询语句,load 使用缓存student = (Student)ses.load(Student.class, 1);System.out.prln(= + student.getName();第二次查
5、询第一次相同的数据,第二次 load 方法就是从缓存里取数据,不会发出 sql 语句到数据查询。/同一个 ses,发出两次get 方法查询Student student = (Student)ses.get(Student.class, 1);System.out.prln(= + student.getName();/不会发出查询语句,get 使用缓存student = (Student)ses.get(Student.class, 1);System.out.prln(= + student.getName();第二次查询第一次相同的数据,第二次不会发出 sql 语句查询数据库,而是到缓存
6、里取数据。/同一个 ses,发出两次 iterate 查询实体对象Iterator iter = ses.createQuery(from Student s where s.id5).iterate();while (iter.hasNext() Student student = (Student)iter.next();System.out.prln(student.getName();System.out.prln();/它会发出查询 id 的语句,但不会发出根据 id 查询学生的语句,因为 iterate 使用缓存iter = ses.createQuery(from Student
7、 s where s.id5).iterate();while (iter.hasNext() Student student = (Student)iter.next();System.out.prln(student.getName();一说到 iterater 查询就要立刻想起:iterater 查询在没有缓存的情况下会有 N+1。执行上面代码查看控制台的 sql 语句,第一次 iterate 查询会发出 N+1 条 sql 语句,第一条 sql语句查询所有的 id,然后根据 id 查询实体对象,有N 个 id 就发出 N 条语句查询实体。第二次 iterate 查询,却只象,不再发 s
8、ql 语句到数据sql 语句,查询所有的 id,然后根据 id 到缓存里取实体对查询了。/同一个 ses,发出两次 iterate 查询,查询普通属性Iterator iter = ses.createQuery(select from Student s where s.id5).iterate();while (iter.hasNext() String name = (String)iter.next();System.out.prln(name);System.out.prln();/iterate 查询普通属性,一级缓存不会缓存,所以发出查询语句/一级缓存是缓存实体对象的iter =
9、 ses.createQuery(select from Student s where s.id5).iterate();while (iter.hasNext() String name = (String)iter.next();System.out.prln(name);执行代码看控制台 sql 语句,第一次发出 N+1 条 sql 语句,第二次还是发出了 N+1 条 sql 语句。因为一级缓存只缓存实体对象,tb 不会缓存普通属性,所以第二次还是发出 sql 查询语句。/两个 ses,每个 ses发出一个 load 方法查询实体对象try ses= HibernateUtils.ge
10、tSes();ses.begranion();Student student = (Student)ses.load(Student.class, 1);System.out.prln(= + student.getName();ses.getTranion().commit();catch(Exception e) e.prStackTrace();ses.getTranion().rollback();finally HibernateUtils.closeSes(ses);第二个 ses调用 load 方法try ses= HibernateUtils.getSes();ses.begr
11、anion();Student student = (Student)ses.load(Student.class, 1);/会发出查询语句,ses间不能共级缓存数据/因为他会伴随着 ses的消亡而消亡System.out.prln(= + student.getName();ses.getTranion().commit();catch(Exception e) e.prStackTrace();ses.getTranion().rollback();finally HibernateUtils.closeSes(ses);第一个 ses的 load 方发出 sql 语句查询实体对象,第二个
12、 ses的 load 方法也会发出 sql 语句查询实体对象。因为 ses间不能共级缓存的数据,所以第二个 ses的 load 方法查询相同的数据还是要到数据库中查询,因为它找不到第一个 ses数据。里缓存的/同一个 ses,先调用 save 方法再调用 load 方法查询刚刚 save 的数据Student student = new Student();student.setName();/save 方法返回实体对象的 idSerializable id = ses.save(student);student = (Student)ses.load(Student.class, id);/
13、不会发出查询语句,因为 save 支持缓存System.out.prln(= + student.getName();先 save 保存实体对象,再用 load 方法查询刚刚 save 的实体对象,则 load 方法不会发出 sql语句到数据库查询的,而是到缓存里取数据,因为 save 方法也支持缓存。当然前提是同一个 ses。/大批量的数据添加for (i=0; i100; i+) Student student = new Student();student.setName( + i);ses.save(student);/每 20 条更新一次if (i % 20 = 0) ses.flu
14、sh();/清除缓存的内容ses.clear();大批量数据添加时,会造成内存溢出的,因为 save 方法支持缓存,每 save 一个对象就往缓存里放,如果对象足够多内存肯定要溢出。一般的做法是先判断一下 save 了多少个对象,如果 save 了 20 个对象就对缓存手动的缓存,这样就不会造成内存溢出。注意:缓存前,要手动调用 flush 方法同步到数据库,否则 save 的对象就没有保存到数据。注意:大批量数据的添加还是不要使用 hibernate,这是 hibernate 弱项。可以使用 jdbc(速度也不会太快,只是比 hibernate 好一点),或者使用工具产品来实现,比如 ora
15、cle 的 Oracle SQL Loader,导入数据特别快。Hibernate 二级缓存二级缓存需要 sesFactory 来管理,它是进初级的缓存,所有人都可以使用,它是共享的。二级缓存比较复杂,一般用第产品。hibernate 提供了一个简单实现,用 Hashtable 做的,只能作为的测试使用,还是需要第产品。使用缓存,肯定是长时间不改变的数据,如果经常变化的数据放到缓存里就没有太大意义了。因为经常变化,还是需要经常到数据查询,那就没有必要用缓存了。hibernate 做了一些优化,和一些第的缓存产品做了集成。老师采用 EHCache 缓存产品。和 EHCache 二级缓存产品集成:
16、EHCache 的 jar 文件在 hibernate 的 lib 里,还需要设置一系列的缓存使用策略,需要一个配置文件 ehcache.xml 来配置。这个文件放在类路径下。/默认配置,所有的类都遵循这个配置也可以对某个对象单独配置:还需要在hibernate.cfg.xml 配置文件配置缓存,让hibernate 知道使用的是那个二级缓存。.hibernate.cache.EhCacheProvidertrue启用二级缓存的配置可以不写的,因为默认就是true 开启二级缓存。必须还手动指定那些实体类的对象放到缓存里在 hibernate.cfg.xml 里:/在里,在后配置或者在实体类文件
17、里:/在里,前配置usage 属性表示使用缓存的策略,一般优先使用 read-only,表示如果这个数据放到缓存里了,则不允许修改,如果修改就会报错。这就要注意放入缓存的数据不允许修改。因为放缓存里的数据经常修改,也就没有必要放到缓存里。使用 read-only 策略效率好,因为不能改缓存。但是可能会出现脏数据,这个问题解决方法只能依赖缓存的超时,比如上面设置了超时为 120 秒,120 后就可以对缓存里对象进行修改,而在 120 秒之内这个对象可能会查询脏数据,因为修改对象后。数据改变了,而缓存却不能改变,这样造成数据不同步,也就是脏数据第二种缓存策略 read-write,当持久对象发生变
18、化,缓存里就会跟着变化,数据库中也改变了。这种方式需要加,效率要比第一种慢。还有两种策看 hibernate 文档,最常用还是第一二种策略。二级缓存测试代码演示:注意上面讲的两个ses分别调用load 方法查询相同的数据,第二个 ses前 ses的 load 方法还是发了 sql 语句到数据库查询数据,这是因为一级缓存只在当享,也就是说一级缓存不能跨 ses。/开启二级缓存,二级缓存是进程级的缓存,可以共享/两个 ses分别调用 load 方法查询相同的实体对象try ses= HibernateUtils.getSes();ses.begranion();Student student =
19、(Student)ses.load(Student.class, 1);System.out.prln(= + student.getName();ses.getTranion().commit();catch(Exception e) e.prStackTrace();ses.getTranion().rollback();finally HibernateUtils.closeSes(ses);try ses= HibernateUtils.getSes();ses.begranion();Student student = (Student)ses.load(Student.class,
20、 1);/不会发出查询语句,因为配置二级缓存,ses可以共享二级缓存中的数据/二级缓存是进程级的缓存System.out.prln(= + student.getName();ses.getTranion().commit();catch(Exception e) e.prStackTrace();ses.getTranion().rollback();finally HibernateUtils.closeSes(ses);如果开启了二级缓存,那么第二个 ses调用的 load 方法查询第一次查询的数据,是不会发出 sql 语句查询数据库的,而是去二级缓存中取数据。/开启二级缓存/两个 se
21、s分别调用get 方法查询相同的实体对象try ses= HibernateUtils.getSes();ses.begranion();Student student = (Student)ses.get(Student.class, 1);System.out.prln(= + student.getName();ses.getTranion().commit();catch(Exception e) e.prStackTrace();ses.getTranion().rollback();finally HibernateUtils.closeSes(ses);try ses= Hibe
22、rnateUtils.getSes();ses.begranion();Student student = (Student)ses.get(Student.class, 1);/不会发出查询语句,因为配置二级缓存,ses可以共享二级缓存中的数据/二级缓存是进程级的缓存System.out.prln(= + student.getName();ses.getTranion().commit();catch(Exception e) e.prStackTrace();ses.getTranion().rollback();finally HibernateUtils.closeSes(ses);
23、注意: 二级缓存必须让 sesfactory 管理,让factory 来清除二级缓存。sesFactory.evict(Student.class);/ 清 除 二 级 缓存 中 所 有student对 象 ,sessesFactory.evict(Student.class,1);/清除二级缓存中 id 为 1 的 student 对象。如果在第一个 ses调用 load 或 get 方法查询数据后,把二级缓存清除了,那么第二个ses调用 load 或get 方法查询相同的数据时,还是会发出 sql 语句查询数据库的,因为缓存里没有数据只能到数据查询。查询数据后会默认自动的放到二级和一级缓存
24、里,如果想查询的数据不放到缓存里,也是可以的。也就是说可以控制一级缓存和二级缓存的交换。.setCacheMode(CacheMode.IGNORE);将一级缓存中的数据往二级缓存里放。ses还 是 用 上 面 代 码 测 试 , 在 第 一 个 ses调 用 load方 法 前 , 执 行ses.setCacheMode(CacheMode.IGNORE);这样 load 方法查询的数据不会放到二级缓存里。那么第二个 ses执行 load 方法查询相同的数据,会发出 sql 语句到数据库中查询,因为二级缓存里没有数据,一级缓存因为不同的 ses不能共享,所以只能到数据查询。上面讲过大批量的数
25、据添加时可能会出现溢出,解决办法是每当天就 20 个对象后就清理一次一级缓存。如果使用了二级缓存,光一级缓存是不够的,还要一二级缓存交互,在 save 方法前调用 ses.setCacheMode(CacheMode.IGNORE)。二级缓存也不会存放普通属性的查询数据,这和一级缓存是一样的,只存放实体对象。ses级的缓存对性能的提高没有太大的意义,因为生命周期太短了。Hibernate 查询缓存一级缓存和二级缓存都只是存放实体对象的,如果查询实体对象的普通属性的数据,只能放到查询缓存里,查询缓存还存放查询实体对象的 id。查询缓存的生命周期不确定,当它关联的表发生修改,查询缓存的生命周期就结
26、束。这里表的修改指的是通过 hibernate 修改,并不是通过数据库客户端登陆到数据库上修改。hibernate 的查询缓存默认是关闭的,如果要使用就要到 hibernate.cfg.xml 文件里配置:true并且必须在程序中手动启用查询缓存,在 query 接口中的 setCacheable(true)方法来启用。/关闭二级缓存,没有开启查询缓存,采用 list 方法查询普通属性/同一个 sessin,查询两次List names = ses.createQuery(select from Student s).list();for (i=0; inames.size(); i+) St
27、ring name = (String)names.get(i);System.out.prln(name);System.out.prln(-);/会发出 sql 语句names = ses.createQuery(select from Student s).setCacheable(true).list();for (i=0; inames.size(); i+) String name = (String)names.get(i);System.out.prln(name);上面代码运行,由于没有使用查询缓存,而一、二级缓存不会缓存普通属性,所以第二次查询还是会发出 sql 语句到数据
28、库中查询。现在开启查询缓存,关闭二级缓存,并且在第一次的list 方法前调用 setCacheable(true),并且第二次 list 查询前也调用这句代码,可以写出下面这样:List names = ses.createQuery(select from Student s).setCacheable(true).list();其它代码不变,运行代码后发现第二次 list 查询普通属性没有发出 sql 语句,也就是说没有到数据库中查询,而是到查询缓存中取数据。/开启查询缓存,关闭二级缓存,采用 list 方法查询普通属性/在两个 ses中调用 list 方法try ses= Hiberna
29、teUtils.getSes();ses.begranion();List names = ses.createQuery(select from Student s).setCacheable(true).list();for (i=0; inames.size(); i+) String name = (String)names.get(i);System.out.prln(name);ses.getTranion().commit();catch(Exception e) e.prStackTrace();ses.getTranion().rollback();finally Hiber
30、nateUtils.closeSes(ses);System.out.prln();try ses= HibernateUtils.getSes();ses.begranion();/不会发出查询语句,因为查询缓存和 ses的生命周期没有关系List names = ses.createQuery(select from Student s).setCacheable(true).list();for (i=0; inames.size(); i+) String name = (String)names.get(i);System.out.prln(name);ses.getTranion().commit();catch(Exception e) e.prStackTrace();ses.getTranion().rollback();finally HibernateUtils.closeSes(ses);运行结果是第二个ses发出的list 方法查询普通属性,没有发出 sql 语句到数据库中查询,而是到查询缓存里取数据,这说明查询缓存
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025-2030中国强化乳制品行业市场发展趋势与前景展望战略研究报告
- 2025-2030中国山茶油行业发展趋势与前景展望战略研究报告
- 二氢欧山芹醇当归酸酯通过抑制PI3K-Akt通路抑制胶质母细胞瘤进展
- 2025-2030中国孕妇营养保健品行业市场全景调研及投资价值评估咨询报告
- 2025-2030中国大数据医药广告行业市场现状供需分析及投资评估规划分析研究报告
- 高三数学复习计划的资源整合
- 信息技术项目费用控制及保障措施
- 历史文化街区语言景观的超语实践研究-以广州沙面为例
- 《化学反应速率与化学平衡:高中化学教学预案》
- 朗诵作品创作与分享计划
- 转让店铺轮胎协议书
- 2025年辽宁省盘锦市中考数学二模试卷
- 完整版新修订《厉行节约反对浪费条例》(课件)
- 公路防汛安全培训课件
- (区县版)-中小学教辅材料征订专项整治工作方案
- 文员岗位笔试试题及答案
- 2025年制冷工职业技能竞赛参考试题库(共500题含答案)
- 安徽卓越县中联盟2024-2025学年高三下学期5月份检测物理试题+答案
- 2024年河北承德辰飞供电服务有限公司招聘真题
- 小米集团2024年环境、社会及管治报告(ESG)
- 手机媒体概论(自考14237)复习题库(含真题、典型题)
评论
0/150
提交评论