




已阅读5页,还剩8页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Hibernate缓存应用的积累与总结杰瑞教育原创,转载请注明出处Hibernate缓存一直比较难掌握,下面就分析和总结原因,相信你就会慢慢清楚了原来Hibernate缓存也是可以轻松掌握的,但前提要求大家必须跟着动手去验证一下,再用心体会,光看是没有用的一、hibernate一级缓存(Session 级别的缓存)hibernate是一个线程对应一个session,一个线程可以看成一个用户。也就是说session级缓存(一级缓存)只能给一个线程用,别的线程用不了,一级缓存就是和线程绑定了。hibernate一级缓存生命周期很短,和session生命周期一样,一级缓存也称session级的缓存或事务级缓存。如果tb事务提交或回滚了,我们称session就关闭了,生命周期结束了。实验1:体验一级缓存:(动手做做) /同一个session中,发出两次load方法查询Employee emp= (Employee )session.load(Employee .class, 1);System.out.println( emp.getName();/不会发出查询语句,load使用缓存emp = (Employee )session.load(Employee .class, 1);System.out.println(emp.getName();第二次查询第一次相同的数据,第二次load方法就是从缓存里取数据,不会发出sql语句到数据库里查询。缓存主要是用于查询 ,hibernate的很多方法都是首先从缓存中取数据如果没有在从数据库中获取,以提升查询效率如:get()/load()、iterate(),而且持久态的对象是会存储在缓存中的。例如:先save保存实体对象,再用load方法查询刚刚save的实体对象,则load方法不会发出sql语句到数据库查询的,而是到缓存里取数据,因为save方法也支持缓存.二、一级缓存特征及其应用:1.Session 级别的缓存,它同session邦定。它的生命周期和session相同。Session消毁,它也同时消毁;2.两个session 不能共享一级缓存,因它会伴随session的生命周期的创建和消毁;3.Session缓存是实体级别的缓存,就是只有在查询对象级别的时候才使用,如果使用HQL和SQL是查询属性级别的,是不使用一级缓存的!切记!4.iterate 查询使用缓存,会发出查询Id的SQL和HQL语句,但不会发出查实体的,它查询完会把相应的实体放到缓存里边,一些实体查询如果缓存里边有,就从缓存中查询,但还是会发出查询id的SQL和HQL语句。如果缓存中没有它会数据库中查询,然后将查询到的实体一个一个放到缓存中去,所以会有N+1问题出现。5.List()和iterate 查询区别:(动手做做)使用iterate,list查询实体对象*N+1问题,在默认情况下,使用query.iterate查询,有可以能出现N+1问题所谓的N+1是在查询的时候发出了N+1条sql语句1:首先发出一条查询对象id列表的sqlN:根据id列表到缓存中查询,如果缓存中不存在与之匹配的数据,那么会根据id发出相应的sql语句list和iterate的区别?list每次都会发出sql语句,list会向缓存中放入数据,而不利用缓存中的数据iterate:在默认情况下iterate利用缓存数据,但如果缓存中不存在数据有可以能出现N+1问题6.Get()和load(),iterate方法都会使用一级缓存,Get与load的区别? (动手做做)1. 对于get方法,hibernate会确认一下该id对应的数据是否存在,首先在session缓存中查找,然后在二级缓存中查找,还没有就查询数据库,数据库中没有就返回null。2. load方法加载实体对象的时候,根据映射文件上类级别的lazy属性的配置(默认为true),分情况讨论:(1)若为true,则首先在Session缓存中查找,看看该id对应的对象是否存在,不存在则使用延迟加载,返回实体的代理类对象(该代理类为实体类的子类,由CGLIB动态生成)。等到具体使用该对象(除获取OID以外)的时候,再查询二级缓存和数据库,若仍没发现符合条件的记录,则会抛出一个ObjectNotFoundException。(2)若为false,就跟get方法查找顺序一样,只是最终若没发现符合条件的记录,则会抛出一个ObjectNotFoundException。小结: 1、get方法首先查询session缓存,没有的话查询二级缓存,最后查询数据库;而load方法首先查询session缓存,没有就创建代理,实际使用数据时才查询二级缓存和数据库 2、如果未能发现符合条件的记录,get方法返回null,而load方法会抛出一个ObjectNotFoundException。 3、load使用代理延迟加载数据,而get方法往往返回有实体数据的对象使用: 1、如果想对一个对象进行增删改查之类,该使用load方法,性能提高,可以使用代理对象,省去了一次和数据库交互的机会,当真正用到该对象的属性时,才跟数据库交互 2、如果你想加载一个对象使用它的属性,该使用get方法7.hiberate3 session 存储过程如下:例如 object 对象Session.save(object);这时候不会把数据放到数据库,会先放到session缓存中去,数据库中没有相应记录,session.flush();才发SQL和HQL语句,数据库中有了相应记录,但是数据库用select查不到,这是跟数据库事物级别有关系。Session.beginTrransaction()。commit();事物提交后可以查询到了。Session.flush()语句但是为什么不写呢,因为commit()会默认调用flush();三、管理一级缓存无论何时,当你给save()、update()或 saveOrUpdate()方法传递一个对象时,或使用load()、 get()、list()、iterate() 或scroll()方法获得一个对象时, 该对象都将被加入到Session的内部缓存中。当随后flush()方法被调用时,对象的状态会和数据库取得同步。 如果你不希望此同步操作发生,或者你正处理大量对象、需要对有效管理内存时,你可以调用evict() 方法,从一级缓存中去掉这些对象及其集合。ScrollableResult cats = sess.createQuery(from Cat as cat).scroll();while ( cats.next() ) Cat cat = (Cat) cats.get(0); doSomethingWithACat(cat); sess.evict(cat);Session还提供了一个contains()方法,用来判断某个实例是否处于当前session的缓存中。如若要把所有的对象从session缓存中彻底清除,则需要调用Session.clear()。四、Hibernate二级缓存(sessionFactory级别缓存)二级缓存需要sessionFactory来管理,它是进初级的缓存,所有人都可以使用,它是共享的。Hibernate二级缓存支持对象缓存、集合缓存、查询结果集缓存,对于查询结果集缓存可选。二级缓存比较复杂,一般用第三方产品。hibernate提供了一个简单实现,用Hashtable做的,只能作为我们的测试使用,商用还是需要第三方产品。几种优秀缓存方案:1、Memcached 分布式缓存系统 2、JBOSS CACHE 3 、EhCache Ehcache 2.1起提供了针对Hibernate的JTA支持。 4、Infinispan 开源数据网格平台使用缓存,肯定是长时间不改变的数据,如果经常变化的数据放到缓存里就没有太大意义了。因为经常变化,还是需要经常到数据库里查询,那就没有必要用缓存了。hibernate做了一些优化,和一些第三方的缓存产品做了集成。这里采用EHCache缓存产品。和EHCache二级缓存产品集成:EHCache的jar文件在hibernate的lib里,我们还需要设置一系列的缓存使用策略,需要一个配置文件ehcache.xml来配置。hibernate.cfg.xml 配置(动手做做) true true !-h3test- net.sf.ehcache.hibernate.EhCacheRegionFactory ehcache.xml true true ehcache配置(ehcache.xml)(动手做做) defaultCache maxElementsInMemory=100 eternal=false timeToIdleSeconds=1200 timeToLiveSeconds=1200 overflowToDisk=false 实体只读缓存 只读缓存 read only,不须要锁与事务,因为缓存自数据从数据库加载后就不会改变。如果数据是只读的,例如引用数据,那么总是使用“read-only”策略,因为它是最简单、最高效的策略,也是集群安全的策略。是性能第一的策略 二级缓存测试代码(动手做做)Session session1 = sf.openSession(); Transaction t1 = session1.beginTransaction(); /确保数据库中有标识符为1的Voucher Voucher voucher = (Vocher) session1.get(Vocher.class, 1); /如果修改将报错,只读缓存不允许修改 /voucher.setName(aaa); mit(); session1.close();Session session2 = sf.openSession(); Transaction t2 = session2.beginTransaction(); voucher = (Vocher) session2.get(Vocher.class, 1); /在二级缓存中查找结果,不会产出sql语句,不操作数据库mit(); session2.close(); sf.close(); 只读缓存不允许更新,将报错Cant write to a readonly object。允许新增,( 新增直接添加到二级缓存)读写缓存 read write对缓存的更新发生在数据库事务完成后。缓存需要支持锁。在一个事务中更新数据库,在这个事务成功完成后更新缓存,并释放锁。锁只是一种特定的缓存值失效表述方式,在它获得新数据库值前阻止其他事务读写缓存。那些事务会转而直接读取数据库 实体读/写缓存 二级缓存测试代码Session session1 = sf.openSession(); Transaction t1 = session1.beginTransaction(); /确保数据库中有标识符为1的Voucher Voucher voucher = (Vocher) session1.get(Vocher.class, 1); /如果修改将报错,只读缓存不允许修改 voucher.setName(aaa); mit(); session1.close(); Session session2 = sf.openSession(); Transaction t2 = session2.beginTransaction(); voucher = (Vocher) session2.get(Vocher.class, 1); /该条目已经被别的事务修改了,此时重新查询一次数据库 mit(); session2.close(); sf.close(); 允许更新,更新后自动同步到缓存。允许新增,新增记录后自动同步到缓存。保证read committed隔离级别及可重复读隔离级别(通过时间戳实现)整个过程加锁,如果当前事务的时间戳早于二级缓存中的条目的时间戳,说明该条目已经被别的事务修改了,此时重新查询一次数据库,否则才使用缓存数据,因此保证可重复读隔离级别非严格读写缓存 nonstrict read write在一个事务中更新数据库,在这个事务完成前就清除缓存,为了安全起见,无论事务成功与否,在事务完成后再次清除缓存。既不需要支持缓存锁,也不需要支持事务。如果是缓存集群,“清除缓存”调用会让所有副本都失效,这通常被称为“拉(pull)”更新策略。如果你的数据读很多或者很少有并发缓存访问和更新,那么可以使用“nonstrict-read-write”策略。感谢它的轻量级“拉”更新策略,它通常是性能第二好的策略。实体非严格读/写缓存 测试代码 略(我想大家会验证了)验证结果允许更新,更新后缓存失效,需再查询一次。 允许新增,新增记录自动加到二级缓存中。整个过程不加锁,不保证。事务缓存 transactional (一定要在JTA环境中)对缓存和数据库的更新被包装在同一个JTA事务中,这样缓存与数据库总是保持同步的。数据库和缓存都必须支持JTA。除非你真的想将缓存更新和数据库更新放在一个JTA事务里,否则不要使用“transactional”策略,因为JTA需要漫长的两阶段提交处理,这导致它基本是性能最差的策略。需要特定缓存的支持和JTA事务支持,此处不演示。集合缓存演示读/写缓存示例,和之前实体缓存测试差不多,其他自测 SessionFactory sf = new Configuration().configure().buildSessionFactory(); Session session1 = sf.openSession(); Transaction t1 = session1.beginTransaction(); /确保数据库中有标识符为1的UserModel UserModel user = (UserModel) session1.get(UserModel.class, 1); user.getVouchers(); mit(); session1.close(); Session session2 = sf.openSession(); Transaction t2 = session2.beginTransaction(); user = (UserModel) session2.get(UserModel.class, 1); user.getVouchers(); mit(); session2.close(); sf.close(); 测试结论:和实体并发策略有相同含义; 但集合缓存只缓存集合元素的标识符,在二级缓存中只存放相应实体的标识符,然后再通过标识符去二级缓存查找相应的实体最后组合为集合返回。查询缓存 (动手做做)1、保证全局配置中有开启了查询缓存。2、修改FarmModel.hbm.xml,添加如下红色部分配置,表示实体缓存并读/写 3、测试代码SessionFactory sf = .new Configuration().configure().buildSessionFactory(); Session session1 = sf.openSession(); Transaction t1 = session1.beginTransaction(); Query query = session1.createQuery(fromVoucher); /即使全局打开了查询缓存,此处也是必须的 query.setCacheable(true); List voucherList = query.list(); mit(); session1.close(); Session session2 = sf.openSession(); Transaction t2 = session2.beginTransaction(); query = session2.createQuery(from Voucher); /即使全局打开了查询缓存,此处也是必须的 query.setCacheable(true); voucherList = query.list(); mit(); session2.close(); sf.close(); 结论:和实体并发策略有相同含义; 和集合缓存类似,只缓存集合元素的标识符,在二级缓存中只存放相应实体的标识符,然后再通过标识符 去二级缓存查找相应的实体最后组合为集合返回。什么时候需要查询缓存? 大多数时候无法从结果集高速缓存获益。必须知道:每隔多久重复执行同一查询。对于那些查询非常多但插入、删除、更新非常少的应用程序来说,查询缓存可提升性能。但写入多查询少的没有用,总失效。管理二级缓存对于二级缓存来说,在SessionFactory中定义了许多方法, 清除缓存中实例、整个类、集合实例或者整个集合。sessionFactory.evict(Cat.class, catId); /evict a particular CatsessionFactory.evict(Cat.class); /evict all CatssessionFactory.evictCollection(Cat.kittens, catId); /evict a particular collection of kittenssessionFactory.evictCollection(Cat.kittens); /evict all ki
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025-2030功能性食品配方创新与监管合规策略报告
- 2025-2030分布式能源存储系统在微电网中的应用与发展趋势分析报告
- 2025-2030共享经济模式创新与可持续发展投资战略研究报告
- 2025-2030共享经济商业模式创新与投资价值评估报告
- 2025年急诊医学创伤抢救模拟试题答案及解析
- 2025年工业互联网平台数字签名技术规范与工业互联网平台产业合作机会报告
- 2025年新能源行业安全管理信息化建设与技术创新报告
- 2025年地热能在农业温室大棚中的能源供应模式报告
- 2025年新能源汽车轻量化材料技术创新与应用研究报告
- 2026年中国新能源汽车产业技术创新与产业升级报告
- 大众集团英语面试题目(3篇)
- 2025年中国外运股份有限公司招聘笔试参考题库含答案解析
- 口腔门诊6S管理制度
- 神经外科住院医师培训工作总结
- 深圳市房屋租赁合同书(空白)
- 2024年中级经济师《经济基础》考试真题及参考答案
- TSGD7002-2023-压力管道元件型式试验规则
- 《铁路危险货物运输管理规则》
- 人教版(2024新版)七年级上册数学期中模拟检测试卷(含答案)
- 高速公路桥梁施工组织
- 城镇污水处理厂工程质量验收规范
评论
0/150
提交评论