Hibernate是一个优秀的Java 持久化层解决方案,是当今主流的对象—关系映射(ORM)工具
对于Hibernate刚刚学习了一周时间了,作为一名java初学者,也有点自己的感受想分享出来,如果这篇文章能有幸被大家看到,也仅供大家娱乐。如果有什么不足之处,欢迎大家多多指点,多多批评。仅供参考,不喜勿喷。
前段时间刚学习了用JDBC来进行java和数据库的连接,来实现对数据的持久化操作和增删改查,但是学习完的感受就是JDBC过于繁琐,因为它无 法直接面对对象,开发效率地,代码又多,还重复,完全不符合java面向对象的思维模式。Hibernate的诞生算是给java程序员很好地解决了这个 问题,所以我们可以忘掉JDBC了,来看看Hibernate是如何实现java的持久化操作的。
Hibernate是一个优秀的Java 持久化层解决方案,是当今主流的对象—关系映射(ORM)工具。它的优势有三点,第一:它是一个开发源代码的对象关系映射框架;第二:对JDBC进行了非 常轻量级的对象封装, 简化了JDBC 繁琐的编码;第三:将JavaBean对象和数据库的表建立对应关系。ORM是持久化层的一种解决方案,它是将java中的类对象及相关属性和相关类与数 据库中的表及表的属性和键做相关的一一映射,来实现java对象和数据库的联系。下面我就来具体说说自己是如何学习Hibernate的。
一:hibernate入门
对 于搭建项目框架编写hibernate配置文件、实体映射文件我就不多说了。首先我们要先用Configuration接口来新建会话工厂,再从 SessionFactory(会话工厂)里获得会话实例(一般情况下,整个应用只有唯一的一个SessionFactory,它应该在应用初始化时被创 建),然后获取Session实例,用Session可以操作数据库和类中的对象,用Transaction接口的commit()和 roolback()方法来提交事务和回滚事物,用Query来对数据库实现查询(用SQL或HQL)。另外在对数据进行增删改查操作 时,Hibernate中的实体对象有三种对象:瞬时状态,持久状态,游离状态。状态不同,实现方法也不相同。大家可以自己慢慢体会。
二:关联映射
既然 Hibernate是关系映射工具,必然存在many-to-one,one-to-many,双向一对多,many-to-many关联。要实现这些操 作,首先实体之间要有关联关系,即通过一个对象持有另一个对象的实例。而在数据库的表中,表的主外键也能实现表与表的关联关系。然后我们就要把这些关联关 系在映射文件(hbm.xml)中体现出来。many-to-one是many的一端应持有one的一端的对象(引用),one-to-many是one 的一端应持有many端的对象集合,双向一对多就是同时配置了单向的一对多和单向的多对一,多对多关联则是将多对多转换成两个一对多,而且为中间表建立实 体类及映射文件,两个端点和中间端分别建立双向一对多关联。
三:HQL实用技术
Hibernate 支持两种主要的查询方式。HQL(Hibernate Query Languge,Hibernate 查询语言)查询是一种面向对象的查询语言,其中没有表和字段的概念,只有类、对象和属性的概念,HQL 是应用较为广泛的方式。Criteria 查询又称为“对象查询”,它用面向对象的方式将构造查询的过程做了封装。
HQL相比与SQL更符合java面向对象思维,也更加简单。HQL中没有表和字段的概念,只有类、对象和属性的概念。例如你要查询名字中带有 “Spring”的一本书,SQL:select * from books where book_name like ‘%Spring%' HQL :from Book b where b.name like 'Spring%' SQL中用到的是数据库中的表名books和字段book_name,而HQL中用到的是Book类名和Book的name属性,而Book类和 books表又是映射关系,所以相当于实现了数据库的操作。是不是更加形象呢?
Criteria 查询用的比较少,从Session中获取Criteria实例,设定限制方法(用到Restrictions常用的查询条件)。相当于把HQL语句转化成一个个方法来实现查询。看自己喜好吧,反正我是觉得HQL更实用一些吧。
四:HQL中的延迟加载和Hibernate高速缓存
HQL 和Criteria查询过程中都会延迟加载,有人觉得这是Hibernate的一个缺陷,我觉得这更像是Hibernate的高明之处。在得到一个 Session实例后,用Book为例,你用Session的get()方法得到一本Book,Book是主对象,而Book又有一个Type关联对象, 但是得到的Book对象不会加载Type关联对象,只有在你需要用到Type关联对象时才会强制加载Type关联对象,具体来说就是关联对象和关联集合的 默认加载计划是:延迟加载,即加载主对象时它们不会被立即加载,而是直到使用这些对象和集合时才发送SQL语句、获取数据、初始化对象和集合,而主对象的 属性默认是被立即加载的。当然这种方式也是可以强制改变的,在用Criteria查询时,你可以在实体类的映射文件中来添加 lazy = “false” 来强制加载。不过不建议这种方式,因为会造成不必要的资源浪费,效率也极低。如果需要,我们可以在编写代码时强制加载效果会更好一些。
总之,这种延迟加载策略会简化SQL语句,提高查询效率。根据不同的用户需要,也可以改变加载策略。
Hibernate缓存有一级缓存和二级缓存,对于一级缓存,其生命周期跟Session的生命周期一样,所以也可以将Hibernate一级缓存 称为Session缓存。Hibernate一级缓存是一个强制的高速缓存。通过get()方法(load()方法也类似),我们可以得到一级缓存数据, 再次查询就不需要get()方法了,直接查询数据对象就行。需要注意的是get()方法是通过id来加载的,而list()方法也会将查询结果放置在一级 缓存中,但是它不会去一级缓存中查找获取数据,原因是list()方法不是通过id加载的,还有iterate方法,例如: Iterator<Seeker> iter = session.createQuery(“from **").iterate(); 该语句只把ID的值放到迭代器中,当遍历的时候,会根据ID的值再去数据库中查。并且该语句会产生N+1次查询。
至于二级缓存是由SessionFactory负责管理,所以也常将二级缓存称为SessionFactory缓存。主要适用于不太重要的数据,所以也没深入的了解。
一周的Hibernate课程学习就到此为止了,Hibernate的相关知识还很多,以后要多在实战项目中运用才能更好地体会。