Fork me on GitHub

Hibernate框架学习(一)

Hibernate Framework

简介:
Hibernate框架是一个全自动的ORM框架,它拥有强大的映射功能,提供了缓存机制、事务管理、拦截器机制、查询语句的多方面支持

本系列笔记可能会遇到的专业词汇有:

  • Framework, 框架,某一类问题的总体解决方案

  • ORM, Object Relationship Mapping, 对象关系映射

  • DATABASE, 数据库,存储数据的一种方式

  • HQL, Hibernate Query Language, Hibernate查询语句

  • Transaction, 事务,一组相关的操作

  • Session, 会话

Hibernate框架的体系架构如下:

体系图示]

本系列笔记包含如下的课程内容:

  • Hibernate框架原理和开发流程
  • 框架缓存机制
  • 对象关系映射
  • 框架提供的查询机制
    • 基于底层的SQL查询机制
    • 基于HQL查询机制
    • 基于Criteria查询机制

Hibernate 框架基础

logo

此章节重点讲解 Hibernate框架开发原理和开发流程,以及环境的配置, 完成一个案例,了解开发的基本流程

章节重点:

  • 开发环境配置
  • 核心API
  • 开发流程
  • 调试

章节难点:

  • Hibernate框架核心API
  • 程序调试

框架介绍

Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。

  • 什么是框架

    • 为解决某一类问题给出的一整套解决方案
    • 给出应用骨架,细节由开发者定制
  • 框架的特点

    • 面向接口
    • 重用性
    • 扩展性
  • 框架的意义

    • 屏蔽底层细节,提高开发效率
    • 结构一致,稳定性好,利于协同开发

每一种框架,都是为了解决某一类的问题(ORM, DI, MVC等); 同时,每一种框架都会有很多具体实现
框架图示

现在,我们看一下JDBC的编程模型
JDBC图示

JDBC优点:
一些JAVA接口的集合,统一和数据库交互的规范,所有数据库都采用统一的操作流程

但,试想一下,JDBC的编程模型存在哪些不足?
question

JDBC存在如下的不足

  • 更换数据库时

    • 面向接口编程时,需要更换实现类
    • 如果不采用接口编程,同时需要更换类
  • 对象和关系的阻抗

    • 不能直接面向对象操作,需要来回转换,在结果集和对象之间转换
    • 此部份代码随机实体类的属性增多,操作将越来越冗余

如下图:
图示

每一段操作DB的代码都需要程序员自己编写SQL指令,自己处理结果集,在大型项目中,这部份JDBC代码的维护量巨大,维护成本较高,而且开发效率低下

如何改变这个现状?

ORM原理

ORM, 全称 Object Relationship Mapping, 也叫对象关系映射,它是一种把对象转换成关系型结构的思想

我们来看一下对象关系的图示
ORM图示

可以看出,对象与关系的映射主要可以分为以下几步:

  • 类型映射到表
  • 属性映射字段[列]
  • 对象实体映射到记录
  • 对象标识映射到主键
  • 对象关系映射到外键 [如果有的话]

通过以上的思想,按此规范操作,则对象与关系就可以互为转换。

在编程上,面向对象和面向关系存在如下异同点:
共同点:

都是用来访问数据库

不同点:

  • 面向对象采用类定义对象,用属性保存数据。 面向过程使用表定义记录,用列保存数据
  • 面向对象中有继承、依赖、关联定义关系。 面向过程使用主键-外建 来定义关系
  • 面向对象使用java代码来访问数据库, 而面向过程使用SQL语法来访问数据库

因此,
ORM 就是要在类和表之间建立一个标准的映射关系,从而使对象可以永久持久化到数据库中,也可将数据库中的数据还原成内存中的对象。提供一种面向对象的方式来访问数据库。

ORM框架原理

  • 不使用ORM框架
    图标

  • 使用ORM框架
    图标

ORM框架产品

  • Hibernate框架 一种全自动的ORM思想实现
  • MyBatis框架 一种半自动的ORM思想实现
  • JPA框架
  • 其它ORM框架

来看看Hibernate框架的优势

  • 全自动的ORM框架
    • 表结构自动生成
    • 流程自动生成
  • 无缝切换 Database
    • 代码0改动,仅更新部份配置文件即可
  • 面向对象操作,更简单易用的API
    • 如:save(obj), update(obj), delete(obj)…

Hibernate 发展历史
图示

开发流程

Hibernate的开发步骤可以简化为以下几步:

  1. 配置Hibernate开发环境 建立项目,导入hibernate必需的jar包,以及驱动jar包
  2. 编写实体类,配置ORM 可以采用XML配置或是注解配置,后面详解
  3. 配置hibernate.cfg.xml文件,以及log4j.properties文件[可选] 此文件包含连接DB的主要信息
  4. 调用Hibernate框架的API 主要涉及到Configuration,SessionFactory, Session,Transaction等

如果是一个普通的项目,则需要事先下载Hibernate框架,可以到[hibernate]官网下载zip档案包

下载完成后,解压后得到如下的目录结构:
图示

如果是maven项目,则只需要在你的pom.xml文件中,添加如下依赖

1
2
3
4
5
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.8.Final</version>
</dependency>

开发实体类

实体类 = JavaBean规范 + 数据库中有表与之对应

JavaBean规范:

  1. 若干私有属性
  2. 一个空参构造
  3. 自动生成的getter/setter方向
  4. 一般需要实现Serializable接口

当然,JavaBean规范在不同的场合,有不同的运用,也有不同的叫法。它仅仅是一种规范。

一个用户实体类如下:

1
2
3
4
5
6
7
8
9
10
11
12
public class User implements Serializable {

//属性
private int id;
private String name;
private int age;

//构造方法
public User() {

}
}

如何把这个实体类映射到数据库,HIBERNATE框架支持两种方式来描述,一为XML,一为注解,如下:

  • XML配置
1
2
3
4
5
6
7
8
9
<hibernate-mapping>
<class name="com.tz.entity.User" table="TBL_USER">
<id name="id">
<generator class="native"/>
</id>
<property name="name" column="name"/>
<property name="age" column="age"/>
</class>
</hibernate-mapping>
  • Annotation配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Entity
@Table(name="TBL_USER")
public class User implements Serializable {

//属性
private int id;
private String name;
private int age;

//构造方法
public User() {

}
@Id
@GeneratedValue
public int getId() { return this.id; }
public void setId(int id) { this.id = id; }
@Column
public String getName() { return this.name; }
public void setName(String name) { this.name = name; }
@Column
public int getAge() { return this.age; }
public void setAge(int age) { this.age = age; }
}

从上面的可以看出,XML与Annotation都可以描述映射,下面是它们的对比图:
图示

注解目前是主流,越来越多的项目中使用注解,在此课程笔记中,我们的案例也将使用注解来描述映射。

Annotation简介

Annotation(注解)是JDK5.0开始推出的特性,提供一些本来不属于程序的Metadata(元数据),写在类名、属性名或方法名上方,表示类名、属性名或方法名具有某种特性.

比如:

  • @Deprecated 表示已过时,不赞成使用
  • @Override 方法重写
  • @SuppressWarnings 消除指定的警告信息
  • @Test 能在JUnit下测试运行

  • @Entity 指定该类是一个实体

  • @Table 映射到表
  • @Id 映射主键
  • @Column 映射普通的属性列
  • @GeneratedValue 指定主键生成策略
  • @Enumerated 映射枚举类型
  • @Transient 不做持久化
  • @Temporal 当属性是日期类型时,指定日期格式

注解配置案例:
图示
枚举相关的操作:
图示

注解书写简洁、明了,有很强的可读性和可编辑性,借助IDE工具,可以很好地给开发者提性和验证

接下来,要开发Hibernate框架的主配置文件hibernate.cfg.xml

这个文件一般命名为:hibernate.cfg.xml, 并且存放在 src 目录下, 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<!DOCTYPE hibernate-configuration PUBLIC 
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<!-- Hibernate主配置文件 -->
<hibernate-configuration>
<session-factory>
<!-- 配置Hibernate连接数据库的基本信息 -->
<property name="hibernate.connection.driver_class">
oracle.jdbc.driver.OracleDriver
</property>
<property name="hibernate.connection.url">
jdbc:oracle:thin:@localhost:1521:XE
</property>
<property name="hibernate.connection.username">jack</property>
<property name="hibernate.connection.password">123456</property>
<!-- 配置数据库方言用来描述连接的数据库类型和版本 -->
<property name="hibernate.dialect">
org.hibernate.dialect.Oracle10gDialect
</property>
<!-- 是否显示SQL语句(执行时,是否在控制台打印执行的SQL语句) -->
<property name="hibernate.show_sql">true</property>
<!-- 是否格式化SQL语句 -->
<property name="hibernate.format_sql">true</property>
<!-- 是否自动执行DDL语句(update表示如果不存在则没有创建;否则,更新) -->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 配置c3p0参数 -->
<!-- 声明使用c3p0连接池 -->
<property name="connection.provider_class">
org.hibernate.c3p0.internal.C3P0ConnectionProvider
</property>
<!-- 设置c3p0连接池 -->
<!-- 最大容量 -->
<property name="c3p0.max_size">20</property>
<!-- 最小容量 -->
<property name="c3p0.min_size">5</property>
<!-- 最大语句对象数量 -->
<property name="c3p0.max_statements">50</property>
<!-- 超时时间 -->
<property name="c3p0.timeout">5000</property>
<!-- 检测超时时间间隔 -->
<property name="c3p0.idle_test_period">2000</property>
<!-- 容量扩容增量 -->
<property name="c3p0.acquire_increment">5</property>
<!-- end of connection pools config -->
<!-- 导入实体类的映射文件 -->
<mapping resource="com/tz/entity/User.hbm.xml" />
</session-factory>
</hibernate-configuration>

备注:
方言(dialect)是一种用来指定目标数据库的手段,这样一来,HIBERNATE就可以根据不同的DB来生成适用于它们的SQL语法。
连接池(Connection Pools),是用来提升连接的使中效率的方式,通过池来管理连接,可以让这些连接重用。

最后,要调用Hibernate API,完成对象的CRUD操作

CRUD, 也叫增删改查,分别是Create, Retrieve, Update, Delete的缩写

Hibernate 核心API包含如下类和接口

  • Configuration 框架配置类,支持通过xml配置、properties配置、以及编程式配置
  • SessionFactory 会话工厂,用来创建 Session实例的工厂
  • Session 会话,是框架操作对象的基础,由它完成CRUD操作
  • Transaction 事务,进行边界控制
  • Query 查询接口,执行HQL语句
  • Criteria 查询接口,以方法的形式查询

编程步骤:

  1. 初始化Configuration实例,并读取配置文件
  2. 创建SessionFactory实例
  3. 通过SessionFactory来创建Session实例
  4. 通过Session开启事务
  5. 通过Session完成CRUD操作
  6. 提交或回滚事务

案例

在之前的基础上,搭建好IDE开发环境后,可以按如下步骤开发

  • 第一步:编写Book实体类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Book implements Serializable {
private int id;
private String name;
private String author;
private Date publish_date;

//get和set方法...
@Id
@GeneratedValue
public int getId() { return this.id; }
@Column(unique=true)
public String getName() { return this.name; }
@Column
public String getAuthor() { return this.author; }
@Column
@Temporal(TemporalType.DATE)
public Date getPublish_date() { return this.publish_date; }
}
  • 第二步: 在hibernate.cfg.xml配置文件中添加 Book的映射
1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE hibernate-configuration PUBLIC 
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<!-- Hibernate主配置文件 -->
<hibernate-configuration>
<session-factory>
<!-- 配置Hibernate连接数据库的基本信息: 详细请查看上面的文档,此处省略 -->
<!-- 导入实体类的映射文件 -->
<mapping class="com.tz.entity.Book" />
</session-factory>
</hibernate-configuration>
  • 第三步:编写代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class BookMgmt {

private static SessionFactory factory;
//使用静态代码块来初始化sessionfactory
static {
Configuration cfg = new Configuration().configure();
//Hibernate4.x中
ServiceRegistry sr = new StandardServiceRegistryBuilder()
.applySettints(cfg.getProperties())
.build();
factory = cfg.buildSessionFactory(sr);
}
//创建Session
private Session getSession() {
return factory == null ? null : factory.openSession();
}
//保存图书
public void save(Book b) {
Session ses = null;
Transaction tx = null;
try {
ses = getSession();
tx = ses.beginTransaction();
//持久化
ses.save(b);
tx.commit(); //提交事务
} catch(HibernateException e) {
e.printStackTrace();
} finally {
if(ses != null) ses.close();
}
}
...
}
  • 第四步:单元测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class BookMgmtTest {

private BookMgmt bm = new BookMgmt();

public void testSave() {
//模拟一个Book对象
Book b = new Book();
b.setAuthor("...");
b.setName("...");
b.setPublish_date(...);
//
bm.save(b);
}
}

本章小结

  • 学习框架就是学原理、配置、API
  • 了解ORM原理
  • 熟练掌握Hibernate编程流程
  • 熟练掌握ORM的Annotation配置
  • 熟练掌握实体类增、删、改、查操作