Upload
zelin-wang
View
379
Download
5
Embed Size (px)
Citation preview
Hibernate对象管理和缓存结构
ORM ——框架 Hibernate3.3
www.sodi.com.cn
Java对象在 JVM中的生命周期
当应用程序通过 new关键字创建一个 Java对象时, JVM会为这个对象分配一块内存空间,只要这个对象被引用变量引用,它就一直存在于内存中。如果这个对象不被任何引用变量引用,它就结束生命周期,此时 JVM的垃圾回收器就会在适当的时候回收它占用的内存。
www.sodi.com.cn
理解 Session的缓存
当 Session的 save( ) 方法持久化一个 Customer对象时, Customer对象被加入到 Session的缓存中,以后即使应用程序中的引用变量不再引用 Customer对象,只要 Session的缓存还没有被清空, Customer对象仍然处于生命周期中。
当 Session的 load( ) 方法试图从数据库中加载一个Customer对象时, Session先判断缓存中是否已经存在这个 Customer对象,如果存在,就不需要再到数据库中检索。
www.sodi.com.cn
理解 Session的缓存Transaction tx = session.beginTransaction();Customer c1 = new Customer("Tom", new HashSet());
// Customer对象被持久化,并且加入到 Session的缓存中session.save(c1);Long id = c1.getId();// c1变量不再引用 Customer对象c1 = null;// 从 Session缓存中读取 Customer对象,使 c2变量引用 Customer对象Customer c2 = (Customer)session.load(Customer.class, id);// 关闭 Session,清空缓存tx.commit();
// 访问 Customer对象System.out.println(c2.getName());
// c2变量不再引用 Customer对象,此时 Customer对象结束生命周期c2 = null;
www.sodi.com.cn
Session缓存的作用
减少访问数据库的频率。应用程序从内存中读取持久化对象的速度明显比到数据库查询数据的速度快多了,因此 Session的缓存可以提高数据访问的性能。
保证缓存中的对象与数据库中的相关记录保持同步。位于缓存中的对象被称为持久化状态(下面会详细介绍),当缓存中持久化对象的状态发生了变换, Session并不会立即执行相关的 SQL 语句,这使得 Session能够将几条相关的 SQL 语句合并成一条 SQL 语句,以便减少访问数据库的次数,从而提高应用程序的性能。
www.sodi.com.cn
进一步理解 Session缓存
Transaction tx = session.beginTransaction();Customer c1 = (Customer)session.load(Customer.class, 1);Customer c2 = (Customer)session.load(Customer.class, 1);System.out.println(c1 == c2);tx.commit();// 关闭 Session,清空缓存session.close();
内存
Session缓存
Customer
栈
数据库
c1
c2
session.load()
www.sodi.com.cn
Session清理缓存
Session在清理缓存时,按照以下顺序执行 SQL 语句: 按照应用程序调用 session.save( ) 方法的先后顺序,执行所有对实体进行插入的 insert语句。
执行所有对实体进行更行的 update语句。 执行所有对集合进行删除的 delete语句。 执行所有对集合元素进行删除、更新或者插入的 SQL语句。
执行所有对集合进行插入的 insert语句。 按照应用程序调用 session.delete( ) 方法的先后顺序,执行所有对实体进行删除的 delete语句。
www.sodi.com.cn
清理缓存的时间点
在默认情况下, Session会在下面的时间点清理缓存: 当应用程序调用 net.sf.hibernate.Transaction的 commit( ) 方法的时候, commit( ) 方法先清理缓存,然后再向数据库提交事务。
当应用程序调用 Session的 find( ) 或者 iterate( ) 时,如果缓存中持久化对象的属性发生了变化,就会先清理缓存,以保证查询结果能反映持久化对象的最新状态。
当应用程序显示调用 Session的 flush( ) 方法的时候。Session进行清理缓存的例外情况是:如果对象使用
native生成器来生成 OI D,那么当调用 Session的save( ) 保存该对象时,会立即执行向数据库插入该实体的 insert语句。
www.sodi.com.cn
设定 Session清理缓存的时间点
Session的 setFlushMode( ) 方法用于设定清理缓存的时间点。 FlushMode类定义了三种不同的清理模式: FlushMode.AUTO、 FlushMode.COMMI T 和FlushMode.NE VE R ,具体如下表:
FlushMode.AUTO是默认值,这也是优先考虑的清理模式,它会保证在整个事务中,数据保持一致。
清理缓存的模式
Session的查询方法
Transaction的 commit() Session的flush()
AUTO 清理 清理 清理
COMMIT 不清理 清理 清理
NEVER 不清理 不清理 清理
www.sodi.com.cn
COMMI T 和 NE VE R 清理模式
如果事务仅包含查询数据库的操作,而不会修改数据库的数据,也可以选用 FlushMode.COMMI T模式,这可以避免在执行 Session的查询方法时先清理缓存。
在多数情况下,应用程序不需要显式调用 Session的 flush( ) 方法, flush( ) 方法适用于以下场合: 插入、删除或更新某个持久化对象会引发数据库中的触发器。
在应用程序中混合使用 Hibernate API 和 JDB C API 。 JDB C驱动程序不健壮,导致 Hibernate在自动清理缓存的模式下无法正常工作。
www.sodi.com.cn
在 Hibernate应用中 Java对象的状态
对于需要被持久化的 Java对象,在它的生命周期中,可处于以下三种状态之一: 临时状态( transient):刚刚用 new语句创建,还没有被持久化,不处于 Session的缓存中。处于临时状态的Java对象被称为临时对象。
持久化状态( persistent):已经被持久化,加入到Session的缓存中。处于持久化状态的 Java对象被称为持久化对象。
游离状态( detached):已经被持久化,但不再处于Session的缓存中。处于游离状态的 Java对象被称为游离对象。
www.sodi.com.cn
临时对象的特征
临时对象具有以下特征: 不处于 Session的缓存中,也就是说,不被任何一个
Session实例关联。 在数据库中没有对应的记录。
在以下情况下, Java对象进入临时状态: 当通过 new语句刚创建了一个 Java对象,它处于临时状态,此时不和数据库中的任何记录对应。
Session的 delete( ) 方法能使一个持久化对象或游离对象转变为临时对象。
www.sodi.com.cn
持久化对象的特征
持久化对象具有以下特征: 位于一个 Session实例的缓存中,也可以说,持久化对象总是被一个 Session实例关联。
持久化对象和数据库中的相关记录对应。 Session在清理缓存时,会根据持久化对象的属性变化,来同步更新数据库。
在以下情况下, Java对象进入持久化状态: save( ) 方法把临时对象转变为持久化对象。 load( ) 或 get( ) 方法返回的对象总是处于持久化状态。 find( ) 方法返回的 List集合中存放的都是持久化对象。 update( ) 、 saveOrUpdate( ) 和 lock( ) 方法使游离对象转变为持久化对象。
www.sodi.com.cn
游离对象的特征
游离对象具有以下特征: 不再位于 Session的缓存中,也就是说,游离对象不被
Session关联。 游离对象是由持久化对象转变过来的,因此在数据库中可能还存在与它对应的记录(前提条件是没有其他程序删除了这条记录)。
在以下情况下, Java对象进入游离状态: 当调用 Session的 close( ) 方法时, Session的缓存被清空,缓存中的所有持久化对象都变为游离对象。如果在应用程序中没有引用变量引用这些游离对象,他们就会结束生命周期。
Session的 evict( ) 方法能够从缓存中删除一个持久化对象,使它变为游离状态。
www.sodi.com.cn
对象的状态转换图
www.sodi.com.cn
Hibernate的二级缓存结构
Hibernate提供了两级缓存,第一级缓存是 Session的缓存。由于 Session对象的生命周期通常对应一个数据库事务或者一个应用事务,因此它的缓存是事务范围的缓存。第一级缓存是必须的,不允许而且事实上也无法被卸载。在第一级缓存中,持久化类的每一个实例都具有唯一的 OI D。
第二级缓存是一个可拔插的缓存插件,它由SessionFactory负责管理。由于 SessionFactory对象的生命周期和应用程序的整个进程对应,因此第二级缓存是进程范围或群集范围的缓存。这个缓存中存放的是对象的散装数据。第二级缓存是可选的,可以在每个类或每个集合的粒度上配置二级缓存。
www.sodi.com.cn
Hibernate的二级缓存结构
Hibernate的第一级缓存(Session缓存 )
Hibernate的第二级缓存 (SessionFactory的外置缓存 )
缓存并发访问策略 查询缓存
缓存适配器 (CatcheProvider)
缓存的实现
www.sodi.com.cn
Hibernate的二级缓存机制
如果在事务范围的缓存中没有查询到相应的数据,还可以到进程范围或群集范围的缓存内查询,如果在进程范围或群集范围的缓存内也没有找到该数据,那么就只好查询数据库。
应用程序 持久化层的第一级缓存(事务范围的缓存 )
持久化层的第二级缓存(进程范围或群集范围的缓存 )数据库
写
读
读
写
写 读
www.sodi.com.cn
配置二级缓存的主要步骤
( 1 ) 选择合适的缓存插件,每一种缓存插件都有自带的配置文件,因此需要手动编辑该配置文件。
( 2 ) 选择需要使用第二级缓存的持久化类,并设置缓存的并发访问策略。 Hibernate既允许在分散的各个映射文件中为持久化类设置第二级缓存,还允许在 Hibernate的配置文件中集中设置第二级缓存,后一种方式更有利于和缓存相关的配置代码的维护。
www.sodi.com.cn
Hibernate API 对于二级缓存的支持load( ) 默认使用二级缓存iterate( ) 默认使用二级缓存List默认往二级缓存中增加数据,但是查询的时候不使用
如果 query对象要使用二级缓存,需要打开查询缓存: < property name=“cache.use_query_cache”> true< /proerty> 调用 Query的 setCachable( true) 方法指明使用查询缓存
www.sodi.com.cn