Hibernate简介及其与Spring框架的整合开发

Hibernate介绍

出现背景

在Hibernate等ORM框架出现之前,Java Web应用通常使用JDBC来进行持久层的数据库访问等操作,但是JDBC存在着很多缺点,比如实现业务逻辑的代码和数据库访问的代码掺杂在一起,使程序结构不清晰,可读性差;在程序代码中嵌入面向关系的SQL语句,使开发人员不能完全运用面向对象的思维来编写程序;业务逻辑和关系数据模型绑定,如果关系模型发生变化,需要手工修改程序代码中所有相关的SQL语句,增加了程序维护的难度等等。

如何解决问题

为了解决直接使用JDBC的诸多弊端,以Hibernate为代表的ORM框架应运而生。Hibernate是一个基于Java的开源的持久化中间件,对JDBC做了轻量的封装。它采用ORM映射机制,负责实现Java对象和关系数据库之间的映射,把SQL语句传给数据库,并且把数据库返回的结果封装成对象。Hibernate内部封装了JDBC访问数据库的操作,向上层应用提供了面向对象的数据库访问API,使得Java程序员可以轻松使用面向对象的编程思维去操纵数据库,从 95% 的公共数据持续性编程工作中解放出来。

Why Hibernate

同样比较流行的ORM还有MyBatis等,Hibernate相比这些框架有以下优势,因此也是我们选择它作为持久层框架的原因,至于Hibernate和MyBatis的详细对比以及MyBatis的优势可以见这篇文章:数据库持久层框架iBatis、myBatis、Hibernate对比

  • Hibernate的DAO层开发比MyBatis简单,Mybatis需要维护SQL和结果映射。
  • Hibernate对对象的维护和缓存要比MyBatis好,对增删改查的对象的维护要方便。
  • Hibernate数据库移植性很好,MyBatis的数据库移植性不好,不同的数据库需要写不同的SQL。
  • Hibernate有更好的二级缓存机制,可以使用第三方缓存。MyBatis本身提供的缓存机制不佳。
对象-关系映射以及应用程序的分层体系结构

Hibernate与Spring的整合开发

了解完Hibernate后,我将通过在电影售票系统大作业中整合Hibernate来介绍该框架的基本配置与使用,主要的开发环境为:Intellij IDEA + SpringMVC + Spring +Hibernate + MySQL

数据库准备

我们小组使用了MySQL数据库来存储数据,并通过MySQL Workbench这一GUI界面对数据库进行管理。
在开始应用开发之前,我们先设计了基本的数据库表和相应字段,并在表之间设置外键关联关系。

基本的数据库EER模式图

在IDEA中引入Hibernate

使用Maven创建项目,在Project Structure的Modules中添加Hibernate模块并指定配置文件为hibernate.cfg.xml,Maven会自动帮助我们下载相应的依赖包。


引入Hibernate

编写Hibernate配置文件

引入Hibernate后,IDE在META-INF目录下为我们自动创建了一个Hibernate的配置文件,我们可以在其中配置数据库及缓存相关的属性,比如设置事务的自动提交属性为true,可以简化业务层的代码编写。

hibernate.cfg.xml

除了上述的配置文件,我们还需要其他的配置文件将Spring与Hibernate整合起来,这里我创建了infrastructure.xml。

infrastructure.xml

可以看到,在该xml配置文件中,我们使用了c3p0数据源,c3p0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。同时我们指定了Spring进行组件扫描的基础包,用来扫描所有Entity注解进而实现Spring的自动装配。再结合上节提到的hibernate.cfg.xml,我们就定义好了Hibernate所需要的session工厂bean,通过session工厂就可以获取session并调用Hibernate内置的CRUD方法。

在该配置文件的最上方还引用了hibernate.properties,该配置文件定义了数据库连接的各种属性,比如url、用户名和密码等供infrastructure.xml引用,可以避免硬编码属性。

hibernate.properties

将数据库表映射成Java实体类

编写完Hibernate所需的配置文件后,就可以成功连接到MySQL数据库。下一步操作就是编写与数据库表相对应的实体类(持久化类),而IDEA强大的一点在于,它可以直接将数据库表映射成Java实体类并加上基本的注解,从而节省大量的时间。

用户实体类

设置Hibernate关联映射

数据库中表与表之间会存在不同的主外键关联关系,而Hibernate作为ORM框架,自然需要将表之间的关系映射成实体类之间的关联映射关系。Hibernate为我们提供了@OneToMany、@ManyToOne、@ManyToMany等多种注解来表示实体类间的关联关系。

以上图中用户和评论之间的双向一对多关联为例,多端作为关联关系的主控端,涉及到两个实体的增删改查操作都应由多端完成,这样可以减少SQL语句的执行,提高数据访问性能。一端作为关联关系的被控端,这种被控使用mappedBy属性来表明,同时一端设置了cascade级联属性表明在对用户进行删除和保存等操作时,该操作也会级联到关联到该用户的所有评论实体,从而保证业务逻辑上的正确性,并且省去了手动保存评论的麻烦。

评论实体

而在上图的评论实体中,我们可以相对应地看到针对User的@ManyToOne注解,而@JoinColumn注解指定了comment表中使用user_id作为外键关联到user表的user_id属性,从而在关系层次上建立起了两个表之间的联系。

编写BaseDAO

设置完实体类之间的关联映射后,就可以进入Hibernate的业务代码编写阶段。根据MVC的分层架构,我们将整个应用分为显示层(View),控制层(Controller),业务逻辑层(Service)和数据访问层(DAO)

分层架构示例

其中Controller层负责处理请求的路由,并调用Service层的业务逻辑方法执行业务,而Service层需要调用DAO层的数据访问方法来实现与底层数据库的交互,每一层之间都面向接口编程,保持了较松的耦合性,同时架构清晰,增强了项目的可维护性和可伸缩性。

在实际编程时,我们通常都是自底向上从DAO层开始编写代码。DAO层封装了与底层数据库交互的方法,而有一些通用的CRUD方法是每一个实体类都需要的,因此这些方法可以被封装成一个基础的BaseDAO泛型接口,每一个实体类各自的DAO接口只需要继承BaseDAO接口的实现即可根据业务需求继续扩展,这也体现了代码复用的思想。

BaseDAO

从上图接口中可以发现BaseDAO定义了很多不同的查询方法,这也就引出了Hibernate另一方面的重要知识,即HQL查询和标准查询。

HQL查询

Hibernate 查询语言(HQL)是一种面向对象的查询语言,类似于 SQL,但不是去对表和列进行操作,而是面向对象和它们的属性。 HQL 查询被 Hibernate 翻译为传统的 SQL 查询从而对数据库进行操作。

尽管能直接使用本地 SQL 语句,但是应该尽可能的使用 HQL 语句,以避免数据库关于可移植性的麻烦,并且体现了 Hibernate 的 SQL 生成和缓存策略。

在 HQL 中一些关键字比如 SELECT ,FROM 和 WHERE 等,是不区分大小写的,但是一些属性比如表名和列名是区分大小写的。

以FROM语句为例展示一下HQL的语法。
如果想要在存储中加载一个完整并持久的对象,可以使用 FROM 语句。

String hql = "FROM Employee";
Query query = session.createQuery(hql);
List results = query.list();

在BaseDAO中我编写了一些工具方法来简化HQL查询代码的编写。

标准查询

Hibernate 提供了操纵对象和相应的 RDBMS 表中可用的数据的替代方法。一种方法是标准的 API,它允许开发者建立一个标准的可编程查询对象来应用过滤规则和逻辑条件。

Hibernate Session 接口提供了 createCriteria() 方法,可用于创建一个 Criteria 对象,使应用程序执行一个标准查询时返回一个持久化对象的类的实例。

以下是一个最简单的标准查询的例子,它只是简单地返回对应于员工类的每个对象:

Criteria cr = session.createCriteria(Employee.class);  
List results = cr.list();

同时可以使用 Criteria 对象可用的 add() 方法去添加一个标准查询的限制,限制包括等于(eq)、大于(gt)、小于(lt)等等逻辑谓词,我也在BaseDAO中将其写成了工具方法,即根据条件类型来构建Criterion。

同时我也添加了上述使用到的ConditionType和Condition等辅助类来简化标准查询的代码。

利用这些工具类和工具方法,可以大大简化标准查询的代码,如下所示:

/**
     * 根据Criterion列表获取集合对象
     *
     * @param criterions
     * @return
     */
    @Override
    public List<T> find(Criterion... criterions) {
        return createCriteria(getCurrentSession(), getEntityClass(), criterions).list();
    }

介绍完BaseDAO中的主要方法后,大作业数据访问层的基础功能就已经搭建好了,之后只需根据业务需求扩展BaseDAO,进而构建Service层和Controller层以完成业务逻辑的处理,这些内容就不再赘述。
至此Hibernate就成功和Spring进行了整合,并展示了它的强大功能。

参考

Hibernate 教程
Hibernate之条件查询(Criteria Queries)
用hibernate+注解实现各种关系映射
数据库持久层框架iBatis、myBatis、Hibernate对比
SSH——hibernate 利用注解实现实体关联映射详解
Spring-SpringMVC-Hibernate在IntelliJ与Maven的环境下搭建
Spring框架教程

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容