1.持久化和ORM
持久化是指把数据(内存中的对象)保存到可持久保存的存储设备中(如硬盘),主要应用于将内存中的数据存储到关系型数据库中,在三层结构中,持久层专注于实现系统的逻辑层面,将数据使用者与数据实体进行关联。
ORM简称对象-关系型数据映射,在编写程序时,处理数据采用面向对象的方式,保存数据却以关系型数据库的方式,因此需要一种能在两者之间进行转换的机制。这种机制称为ORM。ORM保存了对象和关系型数据库表的映射信息。Hibernate映射信息保存在XML格式的配置文件中。
2 Hibernate 核心接口框图
2.1 Configuration类
在启动Hibernate的过程中,Configuration实例首先确定映射文件hibernate.cfg.xml的位置,读取相关的配置信息,最后创建一个唯一的SessionFactory实例,这个唯一的SessionFactory实例负责进行所有的持久化操作。Configuration类的实例只存在于系统的初始化阶段。
2.2 SessionFactory接口
SessionFactory接口负责Hibernate的初始化。具体来说,在Hibernate中SessionFactory实际上起到了一个缓冲区的作用,Hibernate 自动生成的SQL语句,映射数据以及某些可重复利用的数据都可放在这个缓冲区中。同时它还保存了对数据库配置的所有映射关系,维护当前的二级数据缓存和Statement Pool。
一般情况下,一个项目只需要一个SessionFactory,但当项目中要操作多个数据库时,则必须为每个数据库指定一个SessionFactory。
2.2.1 openSession方法和getCurrentSession方法的主要区别
在创建Session实例时,采用openSession,SessionFactory创建的是一个新的Session实例。而getCurrentSession方法创建的Session实例会被绑定到当前线程中。采用openSession方法,在使用完后需要显示调用close方法进行手动关闭。而getCurrentSession方法创建的Session实例则会在提交(commit)或回滚(rollback)操作时自动关闭。
2.3 Session接口
Session对象的生命周期以Transaction对象的事物开始和结束为边界。Session提供了一系列与持久化相关的操作,如读取,创建和删除相关实体对象的实例,这一系列的操作最终将被转换为对数据库中数据的增加,修改,查询和删除操作。所以,Session也被称为持久化管理器。
2.3.1 实体对象的生命周期
对象在生命周期中所处的状态有:瞬时态(Transient),持久态(Persistent)和游离态(Detached)。同一个实体对象进行不同的操作后其状态会进行相互转换。
(1)瞬时态
利用new操作符实例化后的对象所处的状态即为瞬时态,这时还没有存入任何数据库表中。一旦他们不再被其他对象引用时,状态立即丢失,且不能再被访问,只能等待垃圾回收。
(2)持久态
持久态对象与Session实例是相关的,对持久态对象所做的任何操作都将被Hibernate持久化到数据库中。持久态对象总和数据库中的记录相对应,Session对缓存做清理时,会依据持久态对象属性的变化,来同步的更新数据库。当session执行delete()方法时,不仅会从数据库中删除与之对应的记录,还会把它从session的缓存中删除。
(3)游离态
当处于持久态的对象不再与Session实例相关时,该对象就变成了游离态。此时对象中的属性值发生变化,Hibernate不会再将变化同步到数据库中。对于游离态的对象,Session执行delete()方法会从数据库中删除与之对应的记录。游离态与瞬时态的不同在于游离态是有持久态转换来的,因此在数据库还保存有对应的记录,而瞬时态在数据库中是不存在任何记录和它对应的。
2.3.2 使对象进入持久态的方法
update(),saveOrUpdate()和lock()方法可以将游离态对象转换为持久态对象。与save()方法类似,在调用update()方法后,被保存的对象不是立刻就同步到数据库,只有当事物结束的时候才会将实体对象当前的属性值更新到数据库中,不过当需要执行新的同表查询时,为得到准确的查询结果,就需要及时对数据库进行更新。若一个持久态对象与一个瞬时态对象关联,则在允许级联保存的情况下,Session会在清理缓存时将瞬时态对象转换为持久态对象。
saveOrupdate()方法根据实体对象的状态由Hibernate来决定使用什么方法,当传入实体对象是瞬时态时,执行save()操作;当传入是游离态时,执行update()方法;当传入对象为持久态时直接返回,不进行任何操作。
load()方法或者get()方法都是通过标识符的到指定类的持久态对象(需要类型强转),但要求持久化对象必须存在,否则会产生异常。两者的区别在于:
(1)当所查找的记录不存在时,get()方法会返回null,而load()方法则会抛出HibernateException 异常。
(2) get()方法直接返回实体类,load()方法则返回实体的代理类实例。当然,如果将*.hbm.xml中<class>元素的lazy属性设置为false是,则load()方法 也是返回实体类,不返回代理类。而lazy属性是有什么用呢,他表示延迟加载,即当真正需要属性时,才执行真正的数据加载操作,这样做可以降低系统的性能开销。 当lazy()设置为true时,load()返回持久化对象的代理类实例,该代理类实例是在运行时动态生成的,它包括了目标对象的所有属性和方法。但是由于采用了延迟加载,此 代理实例的属性中除了id属性其他都为NULL,只有当代理类实例调用getXXX()方法时,Hibernate才真正到数据库中获得属性值。
(3)load()和get()都是从Session内部缓存中开始查找指定对象,如果没有找到,load()会去Hibernate二级缓存查询,若还未找到,则会发送一条SQL 语句到数据库中进行查询,并根据查询结果生成相应的实体对象。而get()会越过二级缓存,直接发出SQL语句到数据库中完成数据读取。
本文均为自己一字一句整理得到,如果你觉得还不错,请关注我或点赞,至于Query,Criteria和Transaction接口会在接下来的Hql实例讲解博客中再作介绍,谢谢观看!
---------参考资料《Java Web整合开发实战》《Struts2+Spring3+Hibernate框架技术精讲与整合案例》