Hibernate中的缓存机制和抓取策略

合集下载

论述Hibernate中抓取策略

论述Hibernate中抓取策略

本文主要就Hibernate抓取策略加以分析,Hibernate抓取策略(fetching strategy)是指:当应用程序需要在(Hibernate实体对象图的)关联关系间进行导航的时候,Hibernate如何获取关联对象的策略。

抓取策略可以在O/R映射的元数据中声明,也可以在特定的HQL 或条件查询(Criteria Query)中重载声明。

如下几种Hibernate抓取策略:◆连接抓取(Join fetching) - Hibernate通过在SELECT语句使用OUTER JOIN(外连接)来获得对象的关联实例或者关联集合。

◆查询抓取(Select fetching) - 另外发送一条 SELECT 语句抓取当前对象的关联实体或集合。

除非你显式的指定lazy="false"禁止延迟抓取(lazy fetching),否则只有当你真正访问关联关系的时候,才会执行第二条select语句。

◆子查询抓取(Subselect fetching) - 另外发送一条SELECT 语句抓取在前面查询到(或者抓取到)的所有实体对象的关联集合。

除非你显式的指定lazy="false" 禁止延迟抓取(lazy fetching),否则只有当你真正访问关联关系的时候,才会执行第二条select 语句。

◆批量抓取(Batch fetching) - 对查询抓取的优化方案,通过指定一个主键或外键列表,Hibernate使用单条SELECT语句获取一批对象实例或集合。

Hibernate抓取策略会区分下列各种情况:1.Immediate fetching,立即抓取 - 当宿主被加载时,关联、集合或属性被立即抓取。

zy collection fetching,延迟集合抓取- 直到应用程序对集合进行了一次操作时,集合才被抓取。

(对集合而言这是默认行为。

)3."Extra-lazy" collection fetching,"Extra-lazy"集合抓取 -对集合类中的每个元素而言,都是直到需要时才去访问数据库。

hibernate菜鸟教程

hibernate菜鸟教程

hibernate菜鸟教程
Hibernate是一个开源的对象关系映射框架,它提供了将Java
对象映射到关系数据库中的功能,并支持数据库的CRUD操作。

通过Hibernate,开发人员可以摆脱传统的JDBC编程,
简化了数据持久化层的开发工作。

Hibernate的主要特点包括:
1. 对象关系映射:Hibernate的核心功能就是将Java对象和关
系数据库之间进行映射,开发人员不需要编写繁琐的SQL语
句来进行数据的持久化操作,只需要操作Java对象即可。

2. 高度可定制化:Hibernate提供了丰富的配置选项,可以根
据项目的需求进行灵活的配置。

开发人员可以使用XML文件
或者注解来定义映射关系。

3. 数据库无关性:Hibernate可以适用于多种关系数据库,开
发人员不需要关心不同数据库的SQL差异,只需要根据Hibernate的API进行开发即可,从而提高了开发的效率。

4. 缓存机制:Hibernate内置了一级缓存和二级缓存的支持,
可以提高数据的访问效率。

一级缓存是在Session级别的缓存,而二级缓存是在SessionFactory级别的缓存。

5. 延迟加载:Hibernate支持延迟加载机制,可以在需要访问
关联对象时再进行查询,提高了性能。

总之,Hibernate是一个非常强大且灵活的对象关系映射框架,能够极大地简化数据持久化层的开发工作,提高开发效率。

它已经成为了Java开发中非常重要的框架之一。

Hibernate的缓存机制研究综述

Hibernate的缓存机制研究综述

Hibernate的缓存机制研究综述[摘要]Hibernate提供了二级缓存机制,正确应用缓存可以提高应用的运行性能。

本文在研究了Hibernate二级缓存原理、二级缓存策略和第二级缓存存放数据策略的基础上,对程序员使用Hibernate缓存提出了几点建议。

[关键词]Hibernate,缓存原理,缓存策略0引言缓存(Cache)是一块存储区域,最初是用于解决CPU和内存速度不匹配。

为CPU提供一种比一般随机存内存(RAM)存取速度更快的存储设备,让数据存取速度能适应CPU的处理速度。

其实现原理是内存中“空间和时间的局域性”。

现在缓存的概念已被扩充,凡是位于速度相差较大的两种硬件之间的,用于协调两者数据传输速度差异的结构,均可称之为Cache。

不仅在CPU和主内存之间有Cache而且在内存和硬盘之间也有Cache(磁盘高速缓存)。

Hibernate的缓存是介于应用程序和永久性数据存储源之间,通过降低应用程序直接读写永久性数据存储源的频率,提高应用的运行性能。

Hibernate把程序经常的访问的数据放在缓存中,当程序需要这些数据时,先到缓存中查找,如果缓存中存在,直接从缓存中读取;如果缓存中不存在,则到数据库中检索。

Hibernate缓存比较复杂,如果使用合理,则能极大地提高系统性能,但如果使用不合理也会使用系统性能下降。

为此,只有深入研究hibernate缓存原理才能灵活使用hibernate缓存。

Hibernate中的缓存介绍Hibernate使用了一级缓存和二级缓存来提高应用程序的性能。

第一级是Session级别的缓存,Session级别由Hibernate管理,通常不需要程序员干预。

第二级缓存是SessionFactory级别的缓存,该级别的缓存可以配置和更改,并且可以动态加载和卸载。

Hibernate两级缓存结构如图1所示:Hibernate两级缓存的区别第一级缓存就是Session级别的缓存,缓存的数据放在各自的Session的上下文中,默认时已经启动。

Hibernate的缓存机制

Hibernate的缓存机制

Hibernate的缓存机制⼀、缓存的范围分为3类:1、事务范围(单Session即⼀级缓存)事务范围的缓存只能被当前事务访问,每个事务都有各⾃的缓存,缓存内的数据通常采⽤相互关联的对象形式.缓存的⽣命周期依赖于事务的⽣命周期,只有当事务结束时,缓存的⽣命周期才会结束.事务范围的缓存使⽤内存作为存储介质,⼀级缓存就属于事务范围.2、应⽤范围(单SessionFactory即⼆级缓存)应⽤程序的缓存可以被应⽤范围内的所有事务共享访问.缓存的⽣命周期依赖于应⽤的⽣命周期,只有当应⽤结束时,缓存的⽣命周期才会结束.应⽤范围的缓存可以使⽤内存或硬盘作为存储介质,⼆级缓存就属于应⽤范围.3、集群范围(多SessionFactory)在集群环境中,缓存被⼀个机器或多个机器的进程共享,缓存中的数据被复制到集群环境中的每个进程节点,进程间通过远程通信来保证缓存中的数据的⼀致,缓存中的数据通常采⽤对象的松散数据形式.⼆、⼀级缓存: 1、使⽤⼀级缓存的⽬的是为了减少对数据库的访问次数,从⽽提升hibernate的执⾏效率;(当执⾏⼀次查询操作的时候,执⾏第⼆次查询操作,先检查缓存中是否有数据,如果有数据就不查询数据库,直接从缓存中获取数据); 2、Hibernate中的⼀级缓存,也叫做session的缓存,它可以在session范围内减少数据库的访问次数,只在session范围内有效,session 关闭,⼀级缓存失败; 3、⼀级缓存的特点,只在session范围有效,作⽤时间短,效果不是特别明显,在短时间内多次操作数据库,效果⽐较明显。

4、当调⽤session的save/saveOrUpdate/get/load/list/iterator⽅法的时候,都会把对象放⼊session缓存中; 5、session的缓存是由hibernate维护的,⽤户不能操作缓存内容;如果想操作缓存内容,必须通过hibernate提供的evict/clear⽅法操作 6、缓存相关的⽅法(在什么情况下使⽤上⾯⽅法呢?批量操作情况下使⽤,如Session.flush();先与数据库同步,Session.clear();再清空⼀级缓存内容): session.flush();让⼀级缓存与数据库同步; session.evict();清空⼀级缓存中指定的对象; session.clear();清空⼀级缓存中所有的对象;⼆、⼆级缓存:基于应⽤程序级别的缓存,作⽤在SessionFactory范围内的,可以跨多个session,即不同的session都可以访问缓存。

hibernate缓存机制详细分析(一级、二级、查询缓存,非常清晰明白)

hibernate缓存机制详细分析(一级、二级、查询缓存,非常清晰明白)

hibernate缓存机制详细分析(⼀级、⼆级、查询缓存,⾮常清晰明⽩)您可以通过点击右下⾓的按钮来对⽂章内容作出评价, 也可以通过左下⽅的关注按钮来关注我的博客的最新动态。

如果⽂章内容对您有帮助, 不要忘记点击右下⾓的推荐按钮来⽀持⼀下哦如果您对⽂章内容有任何疑问, 可以通过评论或发邮件的⽅式联系我:****************/**********************如果需要转载,请注明出处,谢谢!!在本篇随笔⾥将会分析⼀下hibernate的缓存机制,包括⼀级缓存(session级别)、⼆级缓存(sessionFactory级别)以及查询缓存,当然还要讨论下我们的N+1的问题。

随笔虽长,但我相信看完的朋友绝对能对hibernate的 N+1问题以及缓存有更深的了解。

⼀、N+1问题⾸先我们来探讨⼀下N+1的问题,我们先通过⼀个例⼦来看⼀下,什么是N+1问题:list()获得对象: /** * 此时会发出⼀条sql,将30个学⽣全部查询出来*/ List<Student> ls = (List<Student>)session.createQuery("from Student").setFirstResult(0).setMaxResults(30).list();Iterator<Student> stus = ls.iterator();for(;stus.hasNext();){Student stu = (Student)stus.next();System.out.println(stu.getName());}如果通过list()⽅法来获得对象,毫⽆疑问,hibernate会发出⼀条sql语句,将所有的对象查询出来,这点相信⼤家都能理解Hibernate: select student0_.id as id2_, student0_.name as name2_, student0_.rid as rid2_, student0_.sex as sex2_ from t_student student0_ limit ?那么,我们再来看看iterator()这种情况iterator()获得对象 /** * 如果使⽤iterator⽅法返回列表,对于hibernate⽽⾔,它仅仅只是发出取id列表的sql* 在查询相应的具体的某个学⽣信息时,会发出相应的SQL去取学⽣信息* 这就是典型的N+1问题* 存在iterator的原因是,有可能会在⼀个session中查询两次数据,如果使⽤list每⼀次都会把所有的对象查询上来* ⽽是要iterator仅仅只会查询id,此时所有的对象已经存储在⼀级缓存(session的缓存)中,可以直接获取*/ Iterator<Student> stus = (Iterator<Student>)session.createQuery("from Student").setFirstResult(0).setMaxResults(30).iterate();for(;stus.hasNext();){Student stu = (Student)stus.next();System.out.println(stu.getName());}在执⾏完上述的测试⽤例后,我们来看看控制台的输出,看会发出多少条 sql 语句:Hibernate: select student0_.id as col_0_0_ from t_student student0_ limit ?Hibernate: select student0_.id as id2_0_, student0_.name as name2_0_, student0_.rid as rid2_0_, student0_.sex as sex2_0_ from t_student student0_ where student0_.id=?沈凡Hibernate: select student0_.id as id2_0_, student0_.name as name2_0_, student0_.rid as rid2_0_, student0_.sex as sex2_0_ from t_student student0_ where student0_.id=?王志名Hibernate: select student0_.id as id2_0_, student0_.name as name2_0_, student0_.rid as rid2_0_, student0_.sex as sex2_0_ from t_student student0_ where student0_.id=?叶敦.........我们看到,当如果通过iterator()⽅法来获得我们对象的时候,hibernate⾸先会发出1条sql去查询出所有对象的 id 值,当我们如果需要查询到某个对象的具体信息的时候,hibernate此时会根据查询出来的 id 值再发sql语那么这种 N+1 问题我们如何解决呢,其实我们只需要使⽤ list() ⽅法来获得对象即可。

跟我学Hibernate框架技术——Hibernate框架中的查询缓存及实现相关的应用技术

跟我学Hibernate框架技术——Hibernate框架中的查询缓存及实现相关的应用技术

4、为什么要使用查询缓存 (1)对相同的查询要求避免重复执行
因为如果我们执行的是相同的条件语句,那么是不是可以 利用之前的结果集呢?
(2)应用查询缓存能够提高效率
Hibernate就是为了解决这个问题的而引入Query Cache的。
5、Ehcache数据缓存的解决方案 (1)Ehcache出自Hibernate
在 Hibernate 中使用它作为数据缓存的解决方案。可以通 过/获得相关的信息。
(2)官方网站
(3)下载其系统包 /project/showfiles.php?grou p_id=93232
(1)查询缓存及应用的场合 它是针对HQL语句的缓存(只在以HQL方式进行查询时产生) 不适用于数据变更频繁,查询条件相同的场合。
(2)启用查询缓存-------查询缓存在Hibernate同样是可 配置的,默认是关闭的
2、Hibernate的Query缓存策略的实现过程 (1)在执行Query.list查询时 Hibernate的做法是首先检查是否配置了查询缓存,如 配置了则从查询缓存中查找key为“查询语句+查询参数+分 页条件”的值,如获取不到则从数据库中进行获取。
(4)在Hibernate的系统包中已经包含有Ehcache的系统库
6、实现Hibernate中的查询缓存 (1)需要在hibernate.cfg.xml中进行配置ຫໍສະໝຸດ (2)在映射文件中配置出缓存
(3)如果用ehcache,则还需要配置ehcache.xml
详细请见文档中的说明
(4)在DAO组件中将Query.Cacheable设置为true
(2)Hibernate然后根据这些信息组成一个Query Key
Query Key包括条件查询的请求一般信息:SQL, SQL需 要的参数,记录范围(起始位置rowStart,最大记录个数 maxRows) 等。

跟我学Hibernate框架技术——Hibernate框架中的两级缓存及管理相关的应用技术

跟我学Hibernate框架技术——Hibernate框架中的两级缓存及管理相关的应用技术

(2)所应该注意的问题----使用二级缓存的前置条件
如果我们的 Hibernate 程序对数据库有独占的写访问权, 其他的进程更新了数据库, hibernate 是不可能知道的。 因此,我们对数据库的操作,必需直接通过 hibernate , 如果我们直接调用存储过程,或者自己使用 JDBC 来更新数 据库,Hibernate也是不知道的。
(2)调用evict() 方法从一级缓存中去掉对象及其集合
7 、 Hibernate 的第二级缓存(二级缓存涵盖了应用范围与 集群范围,SessionFactory级别的全局缓存)
( 1 ) SessionFactory 的 缓 存 ---Hibernate 的 第 二 级 缓 存 (SessionFactory级别的全局缓存)
(3)缓存的介质一般是内存,所以读写速度很快
但如果缓存中存放的数据量非常大时,也会用硬盘作为缓 存介质。 缓存的实现不仅仅要考虑存储的介质,还要考虑到管理缓 存的并发访问和缓存数据的生命周期。
(4)利用缓存可以提高查找速度
2、缓存的作用
(1)减少访问数据库的频率。 (2)保证缓存中的对象与数据库中的相关记录保持同步。 (3)保证不出现访问对象图的死循环,以及由死循环引起的JVM 堆栈溢出异常。清理缓存时,会顺序执行一些SQL语句。
缓存是数据库数据在内存中的临时容器,它包含了库表数
据在内存中的拷贝,位于数据库与数据访问层之间。 对于查询操作相当频繁的系统(论坛,新闻发布等),良 好的缓存机制显得尤为重要。
(2)缓存的作用
缓存是介于应用程序和物理数据源之间,其作用是为了降 低应用程序对物理数据源访问的频次,从而提高了应用的 运行性能。 缓存内的数据是对物理数据源中的数据的复制,应用程序 在运行时从缓存读写数据,在特定的时刻或事件会同步缓 存和物理数据源的数据。

hirbernate缓存原理解析

hirbernate缓存原理解析

Hibernate缓存原理:
对于Hibernate这类ORM而言,缓存显的尤为重要,它是持久层性能提升的关键.简单来讲Hibernate就是对JDBC进行封装,以实现内部状态的管理,OR关系的映射等,但随之带来的就是数据访问效率的降低,和性能的下降,而缓存就是弥补这一缺点的重要方法.
缓存就是数据库数据在内存中的临时容器,包括数据库数据在内存中的临时拷贝,它位于数据库与数据库访问层中间.ORM在查询数据时首先会根据自身的缓存管理策略,在缓存中查找相关数据,如发现所需的数据,则直接将此数据作为结果加以利用,从而避免了数据库调
用性能的开销.而相对内存操作而言,数据库调用是一个代价高昂的过程.
一般来讲ORM中的缓存分为以下几类:
1:事务级缓存:即在当前事务范围内的数据缓存.就Hibernate来讲,事务级缓存是基于Session的生命周期实现的,每个Session内部会存在一个数据缓存,它随着Session的创建而存在,随着Session的销毁而灭亡,因此也称为Session Level Cache.
2:应用级缓存:即在某个应用中或应用中某个独立数据库访问子集中的共享缓存,此缓存可由多个事务共享(数据库事务或应用事务),事务之间的缓存共享策略与应用的事务隔离机制密切相关.在Hibernate中,应用级缓存由SessionFactory实现,所有由一个SessionFactory创建的Session实例共享此缓存,因此也称为SessionFactory Level Cache.
3:分布式缓存:即在多个应用实例,多个JVM间共享的缓存策略.分布式缓存由多个应
用级缓存实例组成,通过某种远程机制(RMI,JMS)实现各个缓存实例间的数据同步,任何一个实例的数据修改,将导致整个集群间的数据状态同步.。

hibernate缓存机制详解

hibernate缓存机制详解

Hibernate的cache管理Cache就是缓存,它往往是提高系统性能的最重要手段,对数据起到一个蓄水池和缓冲的作用。

Cache对于大量依赖数据读取操作的系统而言尤其重要。

在大并发量的情况下,如果每次程序都需要向数据库直接做查询操作,它们所带来的性能开销是显而易见的,频繁的网络舆,数据库磁盘的读写操作都会大大降低系统的性能。

此时如果能让数据库在本地内存中保留一个镜像,下次访问的时候只需要从内存中直接获取,那么显然可以带来不小的性能提升。

引入Cache机制的难点是如何保证内存中数据的有效性,否则脏数据的出现将会给系统带来难以预知的严重后果。

虽然一个设计得很好的应用程序不用Cache也可以表现出让人接受的性能,但毫无疑问,一些对读取操作要求比较高的应用程序可以通过Cache获得更高的性能。

对于应用程序,Cache通过内存或磁盘保存了数据库中的当前有关数据状态,它是一个存储在本地的数据备份。

Cache位于数据库和应用程序之间,从数据库更新数据,并给程序提供数据。

Hibernate实现了良好的Cache机制,可以借助Hibernate内部的Cache迅速提高系统的数据读取性能。

Hibernate中的Cache可分为两层:一级Cache和二级Cache。

一级Cache:Session实现了第一级Cache,它属于事务级数据缓冲。

一旦事务结束,这个Cache也随之失效。

一个Session的生命周期对应一个数据库事务或一个程序事务。

Session-cache保证了一个Session中两次请求同一个对象时,取得的对象是同一个JAVA 实例,有时它可以避免不必要的数据冲突。

另外,它还能为另一些重要的性能提供保证:1:在对一个对象进行自我循环引用时,不至于产生堆栈溢出。

2:当数据库事务结束时,对于同一个数据库行,不会产生数据冲突,因为对于数据库中的一行,最多只有一个对象来表示它。

3:一个事务中可能会有很多个处理单元,在每一个处理单元中做的操作都会立即被另外的处理单元得知。

Hibernate的工作原理

Hibernate的工作原理

Hibernate的工作原理Hibernate是一个开源的Java持久化框架,它能够将Java对象映射到关系型数据库中,并提供了一套简单而强大的API,使得开辟人员能够更加方便地进行数据库操作。

Hibernate的工作原理主要包括以下几个方面:1. 对象关系映射(ORM):Hibernate使用对象关系映射技术将Java对象与数据库表之间建立起映射关系。

开辟人员只需要定义好实体类和数据库表之间的映射关系,Hibernate就能够自动地将Java对象持久化到数据库中,或者将数据库中的数据映射成Java对象。

2. 配置文件:Hibernate通过一个配置文件来指定数据库连接信息、映射文件的位置以及其他一些配置信息。

配置文件通常是一个XML文件,其中包含了数据库驱动类、连接URL、用户名、密码等信息。

开辟人员需要根据自己的数据库环境进行相应的配置。

3. SessionFactory:Hibernate的核心组件是SessionFactory,它负责创建Session对象。

SessionFactory是线程安全的,通常在应用程序启动时创建一次即可。

SessionFactory是基于Hibernate配置文件和映射文件来构建的,它会根据配置文件中的信息来创建数据库连接池,并加载映射文件中的映射信息。

4. Session:Session是Hibernate的另一个核心组件,它代表了与数据库的一次会话。

每一个线程通常会有一个对应的Session对象。

Session提供了一系列的方法,用于执行数据库操作,如保存、更新、删除、查询等。

开辟人员通过Session对象来操作数据库,而不直接与JDBC打交道。

5. 事务管理:Hibernate支持事务的管理,开辟人员可以通过编程方式来控制事务的提交或者回滚。

在Hibernate中,事务是由Session来管理的。

开辟人员可以通过调用Session的beginTransation()方法来启动一个事务,然后根据需要进行提交或者回滚。

hibernate二级缓存总结

hibernate二级缓存总结

2、缓存策略 1.对象缓存 2.查询缓存 3.页面缓存 1.动态页面缓存 2.Servlet 缓存 3.页面片段缓存
3、缓存分类 1. Web 缓存: i. ii. 2. 3. 浏览器缓存:ajax(在客户端缓存)、HTTP 协议 代理服务器缓存
操作系统缓存:如用于减少磁盘操作 数据库缓存: i. ii. iii. iv. v. 结果缓存: 排序缓存 插入缓存 日志缓存 ………………
2、测试代码 Java 代码 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. mit(); session2.close(); sf.close(); 6 / 13 farm = (FarmModel) session2.get(FarmModel.class, 1); Session session2 = sf.openSession(); Transaction t2 = session2.beginTransaction(); Session session1 = sf.openSession(); Transaction t1 = session1.beginTransaction(); //确保数据库中有标识符为 1 的 FarmModel FarmModel farm = (FarmModel) session1.get(FarmModel.class, 1); mit(); session1.close(); public static void nonstrictReadWriteTest () { SessionFactory sf = new Configuration().configure().buildSessionFactory();

Hibernate的缓存机制概念

Hibernate的缓存机制概念

Hibernate的缓存机制概念:
java对象的属性(通常是一些集合类型的属性)占用的内存空间。

如果对象的占用的内存很大就称为重量级的对象。

如果对象的内存小就称为轻量级的对象。

Session 的缓存被称为hibernate的第一级缓存。

SessionFactory的外置缓存称为hibernate 的二级缓存。

这两个缓存都位于持久层,它们存放的都是数据库数据的拷贝。

SessionFactory 的内置缓存存放元数据和预定义SQL, SessionFactory的内置缓存是只读缓存。

Session 缓存的三大作用:
1,减少数据库的访问频率,提高访问性能。

2,保证缓存中的对象与数据库同步,位于缓存中的对象称为持久化对象。

3,当持久化对象之间存在关联时,Session 保证不出现对象图的死锁。

Session 如何判断持久化对象的状态的改变呢?
Session 加载对象后会为对象值类型的属性复制一份快照。

当Session 清理缓存时,比较当前对象和它的快照就可以知道那些属性发生了变化。

Session 什么时候清理缓存?
1,commit() 方法被调用时
2,查询时会清理缓存,保证查询结果能反映对象的最新状态。

3,显示的调用session 的flush方法。

session 清理缓存的特例:
当对象使用native 生成器时会立刻清理缓存向数据库中插入记录。

【黑马程序员】Hibernate二级缓存

【黑马程序员】Hibernate二级缓存

【黑马程序员】Hibernate二级缓存Hibernate二级缓存机制为什么要有缓存应用程序的数据在缓存均保存在永久介质上,当应用程序需要使用这样的资源时,就需要从永久介质中获取,在获取的时,需要考虑到cpu,Io,Disk读写等等因素,效率并不优秀,缓存是存在于永久介质和应用程序中的一片空间,缓存的出现将原来由应用程序直接和永久介质打交道,转化通过缓存和永久介质打交道,应用程序和缓存打交道,降低应用程序和永久介质之间数据交互的频率,从而提升应用程序的运行性能Hibernate中一级缓存缓存的区别在hibernate中分为一级缓存和二级缓存,其中一级缓存是session级别的缓存,二级缓存是sessionFacotry级别的缓存,二级缓存弥补一级缓存的不足。

一级缓存的数据是针对单次操作而设计,服务于一次请求操作。

由于单次操作的数据量不会涉及很多数据,因此一级缓存存储数据量较小,生命周期较短。

并且单次数据操作完毕后,下一次请求的数据将无法使用上一次缓存的数据。

二级缓存有效弥补一级缓存的缺陷,在现有一级缓存基础上,在多次请求操作间进行数据共享,有效减少访问永久介质的次数。

且Hibernate的二级缓存缓存是通过外部技术实现的,通过使用不同的缓存供应商提供的缓,也称作SessionFactory级别缓存存技术,为Hibernate加开一级缓存,可根据需要进行安装卸载。

Hibernate二级缓存的组成及数据加入二级缓存由4个区域组成:1.类对象缓存区2.类集合缓存区3.时间戳4.查询缓存区什么情况下会影响二级缓存 Get/Load Hql/Sql/QBC都会影响二级缓存测试的方案(这里以hql为主,QBC,HQL,SQL同理):1.通过hql查询数据2.关闭session ,再打开session,重新获得数据3.如果有数据则证明该数据从二级缓存中获得,而如果没有数据表示hql不会影响二级缓存4.测试的结果:是如果采用oid进行查询,可以从二级缓存中获取,而如果进行hql查询,那么此时不会获得数据:分析结果:在于hibernate本身不具备分析sql的能力,真正具有分析能力的只是数据库,针对hql语句,他并不知道你所执行的sql语句真正的含义是什么,所以当你在使用hql 语句时,它只能将数据放入到一级缓存中再将数据加载进入到二级缓存中测试2:以oid为主的测试,oid的数据都会从从一级缓存中去查询加入二级缓存的规则:1.若是通过oid查询‐>会先到session中查询数据,接着如果session中没有数据(有数据则直接返回),会从二级缓存中获取数据(二级缓存中若有数据会将数据加载进入一级缓存,再由一级缓存返回数据),若二级缓存中没有数据,会从db中获取数据,db会将数据加载进入到一级缓存,再同步到二级缓存,再由一级缓存将数据返回二级缓存对象介绍1.类对象缓存区:是真正存放数据的地方,所有真实的数据都存放在这个位置,可以说如果没有这个区域,那么hibernate将无法存储数据,其他的数据都是在为这片区域服务的,而这片区域中存放的都是散装数据(即非Java对象的数据,是由二级缓存供应商自己组合的数据)2.类集合缓存区:该区域存放的是类对象的集合对象,即类对象中存放的是真实数据,但集合缓存区存放的是类对象中的集合对象的oid3.时间戳缓存区:因为hibernate并不知道所执行的sql的含义是什么(能识别sql的只有数据库),当我们使用hibernate的query对象进行update操作的操作时,hibernate 并不知道我们到底修改了什么样的数据,故将我们开始执行这条sql的的时间段的所有数据从二级缓存中进行销毁4.查询缓存区:因为hibernate不具备识别SQL/QBC/Hql的能力,所以hibernate不能通过SQL/QBC/Hql等来加载数据,hibernate为了解决这个问题,创建了一个查询缓存区,类似于一个map,会将sql为key,以查询结果作为value来进行查询。

关于Hibernate缓存机制的研究

关于Hibernate缓存机制的研究

关于Hibernate缓存机制的研究摘要:Hibernate是一个开源的对象关系框架,它对JDBC进行了封装,java程序员可以通过Hibernate框架用对象编程的方式操纵数据库。

而使用Hibernate缓存,减少了项目当中应用程序与数据库的交互,从一定程度上提高了项目运行的效率。

主要探讨Hibernate框架的缓存实现机制与相关的应用策略。

关键词:Hibernate;Session缓存;SessionFactory缓存;持久层1 Hibernate的缓存机制缓存是用于存放数据的内存区域,当应用系统与数据库交互时,把交互过的数据保存到缓存中,当应用系统再次从数据库中读取相同的数据时,就可以从缓存中直接取出数据,而不用再次同数据库交互,从而减少了与数据库交互的次数,提高了应用系统的运行效率,当数据库中的数据被修改或被删除时,那缓存中与之对应的数据也会被修改或被删除,这样可以将缓存中的数据与数据库中的数据同步,保证缓存数据的有效性。

1.1 Hibernate一级缓存Hibernate一级缓存也称为Session缓存,通过将数据存放在Session对象中实现,Session缓存不能通过应用程序或者相关配制人为取消,因此Hibernate一级缓存是事务级别缓存,当session所存在的事务结束时,缓存中的所有数据都会丢失。

一级缓存是Session对象维护一个Key-value型的Map对象,当通过Session存储实体对象时,Session会将实体对象的类型或标识存储到Map对象的key中,将实体对象存储到Map对象的Value 中,当通过Session读取实体对象数据时,Session会跟据实体对象的类型或标识到Map对象中查找,查看是否已存储过这个对象,如果找到则返回这个实体对象,找不到则从数据库中查询。

Hibernate一级缓存是全自动的,不能人为对其干预,但可以通过Session中的方法对它进行管理,包括以下两种:①使用evict()方法从缓存中移除缓存对象,当缓存对象被移出时,该对象的状态会从持久化状态变为托管状态;②使用clear()将缓存中的所有对象全部清除。

ch03_hibernate_lazy_fetch_缓存

ch03_hibernate_lazy_fetch_缓存

总结
Hibernate抓取策略
• Hiberante抓取策略指的是加载一个对象时怎样获得与之相关的关联对象 • 抓取策略可以用在表示关联对象的标签里 – <one-to-one fetch=“select | join”> – <many-to-one fetch=“select | join”> – <set fetch=“select | join | subselect”> select: 表示先查询对象本身,再根据关联字段查询关联表的数据 join: 表示对象本身和其关联对象用一个左外连接(left outer join)语句一 起获得,该选项会忽略其标签上lazy的设置 subselect: 表示子查询
SessionFactory session1
cache cache
session2
DB
cache
Hibernate一级缓存
• 当应用程序调用Session的save()、upate()、saveOrUpdate()、load()、get()、 find()以及调用查询接口的list()、iterate()、filter()方法时,如果Session的 缓存中不存在相应的对象,hibernate就会把该对象加入到一级缓存中。 • 管理一级缓存 – evict(Object o): 从缓存中清除指定的对象 – clear(): 清空缓存中的所有对象
缓存的概念
• 缓存是计算机领域非常通用的概念,它介于应用程序和永久性数据存 储源( 如硬盘上的文件或数据库 )之间,其作用是降低应用程序直接读 写永久性数据存储源的频率,从而提高应用程序的运行性能。缓存中 的数据是数据存储源中数据的拷贝,应用程序在运行时直接读写缓存 中的数据,只是在某些特定时刻按照缓存中的数据来同步更新数据存 储源。 • 缓存的物理介质通常时内存,而永久性数据存储源的物理介质通常是 硬盘或磁盘,读写内存的速度比读硬盘的速度快,从而提高应用程序 的效率

Hibernate优化方案

Hibernate优化方案

详解如何对Hibernate进行优化的方案一、批量修改和删除在Hibernate 2中,如果需要对任何数据进行修改和删除操作,都需要先执行查询操作,在得到要修改或者删除的数据后,再对该数据进行相应的操作处理。

在数据量少的情况下采用这种处理方式没有问题,但需要处理大量数据的时候就可能存在以下的问题:占用大量的内存。

需要多次执行update/delete语句,而每次执行只能处理一条数据。

以上两个问题的出现会严重影响系统的性能。

因此,在Hibernate3中引入了用于批量更新或者删除数据的HQL语句。

这样,开发人员就可以一次更新或者删除多条记录,而不用每次都一个一个地修改或者删除记录了。

如果要删除所有的User对象(也就是User对象所对应表中的记录),则可以直接使用下面的HQL语句:delete User而在执行这个HQL语句时,需要调用Query对象的executeUpdate()方法,具体的实例如下所示:String HQL="delete User";Query query=session.createQuery(HQL);int size=query.executeUpdate();采用这种方式进行数据的修改和删除时与直接使用JDBC的方式在性能上相差无几,是推荐使用的正确方法。

如果不能采用HQL语句进行大量数据的修改,也就是说只能使用取出再修改的方式时,也会遇到批量插入时的内存溢出问题,所以也要采用上面所提供的处理方法来进行类似的处理。

二、使用SQL执行批量操作在进行批量插入、修改和删除操作时,直接使用JDBC来执行原生态的SQL 语句无疑会获得最佳的性能,这是因为在处理的过程中省略或者简化了以下处理内容:● HQL语句到SQL语句的转换。

● Java对象的初始化。

● Java对象的缓存处理。

但是在直接使用JDBC执行SQL语句时,有一个最重要的问题就是要处理缓存中的Java对象。

关于hibernate缓存的问题

关于hibernate缓存的问题

1.关于hibernate缓存的问题:1.1.1.基本的缓存原理Hibernate缓存分为二级,第一级存放于session中称为一级缓存,默认带有且不能卸载。

第二级是由sessionFactory控制的进程级缓存。

是全局共享的缓存,凡是会调用二级缓存的查询方法都会从中受益。

只有经正确的配置后二级缓存才会发挥作用。

同时在进行条件查询时必须使用相应的方法才能从缓存中获取数据。

比如Query.iterate()方法、load、get方法等。

必须注意的是session.find方法永远是从数据库中获取数据,不会从二级缓存中获取数据,即便其中有其所需要的数据也是如此。

查询时使用缓存的实现过程为:首先查询一级缓存中是否具有需要的数据,如果没有,查询二级缓存,如果二级缓存中也没有,此时再执行查询数据库的工作。

要注意的是:此3种方式的查询速度是依次降低的。

1.2.存在的问题1.2.1.一级缓存的问题以及使用二级缓存的原因因为Session的生命期往往很短,存在于Session内部的第一级最快缓存的生命期当然也很短,所以第一级缓存的命中率是很低的。

其对系统性能的改善也是很有限的。

当然,这个Session内部缓存的主要作用是保持Session内部数据状态同步。

并非是hibernate为了大幅提高系统性能所提供的。

为了提高使用hibernate的性能,除了常规的一些需要注意的方法比如:使用延迟加载、迫切外连接、查询过滤等以外,还需要配置hibernate的二级缓存。

其对系统整体性能的改善往往具有立竿见影的效果!(经过自己以前作项目的经验,一般会有3~4倍的性能提高)1.2.2.N+1次查询的问题执行条件查询时,iterate()方法具有著名的“n+1”次查询的问题,也就是说在第一次查询时iterate方法会执行满足条件的查询结果数再加一次(n+1)的查询。

但是此问题只存在于第一次查询时,在后面执行相同查询时性能会得到极大的改善。

NHibernate的缓存管理机制

NHibernate的缓存管理机制

缓存管理面临的主要问题缓存作为一个数据中心,具备添加、更新、删除数据的操作,因此跟数据库类似,会存在事务性、并发情况下数据一致性等问题需要解决使用缓存比较典型的方式如下面代码:Database db = new Database();Transaction tx = db.BeginTransaction();try{//从缓存读取MyEntity1 entity1 = cache.Get<MyEntity1>("pk of entity1");//缓存中没有时从数据库读取if (entity1 == null) entity1 = db.Get<MyEntity1>("pk of entity1");//对entity1进行处理updated = db.Update(entity1); //entity1的更新保存到数据库中if (updated) cache.Put(entity1); //数据库更新成功,则更新缓存//事务中的其他处理mit();}catch{tx.Rollback();throw;}上面的示例代码,是在一个事务性环境中使用缓存,存在更新操作(非只读缓存),如果这是一个共享缓存,这样的使用方式存在很多问题,比如说: 如果事务中的其他处理导致异常,数据库中对entity1的更新可以被回滚掉,但是cache中的entity1已经被更新了,如果不处理这样的情况后续从cache中读出的entity1就是一个不正确的数据所以,要正确的使用缓存,必须有一个完善的方案,充分考虑事务、并发等状况,确保数据的正确性、一致性NHibernate 2个级别的缓存机制相对于session来说,一级缓存是私有缓存,二级缓存是共享缓存session加载实体的搜索顺序为: 1. 从一级缓存中查找;2. 从二级缓存中查找;3. 从数据库查找一级缓存在事务之间担当了一个隔离区域的作用,事务内对实体对象的所有新增、修改、删除,在事务提交之前对其他session是不可见的,事务提交成功之后批量的将这些更新应用到二级缓存中这样的2级缓存机制能够在很大程度上确保数据的正确性(比如前面示例代码中事务失败的情况下,就不会将数据更新到二级缓存中,防止了二级缓存出现错误的数据),以及防止ReadUncommited等其他一些事务一致性问题内部实现上,对一级缓存的管理很简单,所有已加载的实体(以及已经创建proxy但未加载的实体等)都被缓存在持久化上下文(NHibernate.Engine.StatefulPersistenceContext)中待新增、更新、删除的实体,使用3个列表缓存起来,事务提交的时候将他们应用到数据库和二级缓存中(Flush调用或者因为查询等导致的NHibernate自动执行的Flush操作也会将他们应用到数据库,但不会应用到二级缓存中,二级缓存只在事务提交成功之后才更新)中这3个列表维护在SessionImpl中,以后添加的新功能特性以及代码本身的重构动作相当多,这3个列表维护在中二级缓存因为是共享缓存,存在并发更新冲突,但又必须保证二级缓存数据的正确性,因此处理机制就复杂得多。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

一级缓存:
一级缓存生命周期很短和session的生命周期一致,一级缓存也叫session级的缓存或事务级缓存
一级缓存是缓存实体对象的,不缓存普通属性
session间不能共享一级缓存数据
支持一级缓存的方法:
load/get/iterate查询实体对象
save方法
所以在保存大量数据时,缓存中会存在大量的数据,为了解决问题,可以做一下处理:
if (i % 20 == 0) {
session.flush();
//清除缓存的内容
session.clear();
}
如果要导入大量的数据时,使用JDBC更好,或者使用数据库相关的工具如:Oracle SQL Loader
要查询数据,如果一级缓存已经存在需要的实体对象,则直接使用,不会发出查询语句。

二级缓存:
二级缓存也称为进程级的缓存或SessionFactory级的缓存,二级缓存可以被所有的session共享
二级缓存的生命周期和SessionFactory的生命周期一致,SessionFactory可以管理二级缓存
二级缓存的环境配置:
将HIBERNATE_HOME/etc/ehcache.xml文件拷贝到src目录下
在hibernate.cfg.xml文件中加入缓存产品的提供商
<property
name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProv ider</property>
<!-- 启用二级缓存,这也是它的默认配置 -->
<property
name="e_second_level_cache">true</property> hibernate.cfg.xml中指定哪个类实体使用二级缓存:
<class-cache class="com.bjpowernode.hibernate.Student" usage="read-only"/>
可以在映射文件中采用<cache>标签指定或在hibernate.cfg.xml文件中统一指定
注意使用的策略,通常采用read-only和read-write
缓存原则:
缓存原则:通常读远远大于写的数据进行缓存
二级缓存主要是缓存实体对象的
session可以共享二级缓存中的数据
一级缓存和二级缓存的交互
//禁止将一级缓存中的数据放到二级缓存中
session.setCacheMode(CacheMode.IGNORE);
注意大批量数据更新时,如果配置了二级缓存建议禁用一级缓存和二级缓存的交互
session.setCacheMode(CacheMode.IGNORE);
if (i % 20 == 0) {
session.flush();
//清除缓存的内容
session.clear();
}
查询缓存:
查询缓存缓存内容:
查询缓存是缓存普通属性结果集的
对实体对象的结果集会缓存id,根据id从一级缓存和二级缓存中取,如果没有,则发出语句从数据库主查找
查询缓存的生命周期:
当关联的表发生修改,查询缓存的生命周期结束
查询缓存的配置和使用:
在hibernate.cfg.xml文件中加入配置:
<!-- 启用查询缓存,默认是false是不起用的 -->
<property
name="e_query_cache">true</property>
在程序中使用:
query.setCacheable(true)
List names = session.createQuery("select from Student s")
.setCacheable(true)
.list();
查询缓存和session的生命周期没有关系
查询缓存只对query.list()起作用,query.iterate()查询普通属性不会使用查询缓存,
默认query.list()每次执行都会发出查询语句
List students = session.createQuery("select s from Student s")
.list();
跨session:开启查询缓存,关闭二级缓存,那么查询缓存就会缓存实体对象的id,使用查询缓存,然后迭代输出,如果内存中有相关数据,则会没迭代一个就会发送一条根据id查询的sql语句(n+1);配置二级缓存和查询缓存是菜会不发出sql语句。

抓取策略:
单端代理:
hibernate抓取策略,单端代理的批量抓取
设置fetch=”select”,如
<many-to-one name="classes" column="classesid" fetch="select"/>
fetch="select",另外发送一条select语句加载当前对象的关联对象或集合
设置fetch="join",如:
<many-to-one name="classes" column="classesid" fetch="join"/>
fetch="join",hibernate会通过一个select语句连接(内联,此时many-to-one设置为非空/外联)抓取其关联对象或集合
fetch="join",那么lazy失效
fetch="join",只影响get和load,对hql没有影响
为了防止n+1问题可以采用预先抓取的策略,如:
select s from Student s join fetch s.classes
fetch为select或join不影响hql,它影响的是load,get方法
集合代理:
保持默认,同fetch="select",如:
<set name="students" order-by="id" inverse="true" cascade="all" fetch="select">
fetch="select",另外发送一条select语句加载当前对象的关联对象或集合
设置fetch="join",如:
<set name="students" order-by="id" inverse="true" cascade="all" fetch="join">
fetch="join",hibernate会通过一个select语句连接(内联/外联)抓取其关联对象或集合
fetch="join",那么lazy失效
fetch="join",只影响get和load,对hql没有影响
设置fetch="subselect",如:
<set name="students" order-by="id" inverse="true" cascade="all" fetch="subselect">
fetch="subselect",另外发送一条select语句抓取在前面查询到的所有实体的关联集合
fetch="subselect",不影响get.load,会影响hql查询
批量抓取:
batch-size属性,可以批量加载实体类,参见Classes.hbm.xml
<class name="com.bjpowernode.hibernate.Classes" table="t_classes" batch-size="10">
或者查询时使用fetch:
List students = session.createQuery("select s from Student s join fetch s.classes where s.id in(:ids)")
.setParameterList("ids", new Object[]{1, 11, 21, 31, 41, 51, 61, 71, 81, 91})
.list();
batch-size属性,可以批量加载实体类,参见Classes.hbm.xml
<set name="students" order-by="id" inverse="true" cascade="all" batch-size="3">。

相关文档
最新文档