精通Hibernate

今天去公司上班了,公司后台框架是hibernate+springMvc,虽然之前看过hibernate,但是没有在实际的开发过程中用到,很多都忘记了,就准备看孙卫琴的《精通Hibernate》。

Java对象持久化技术概论

从不同的角度解释hibernate:

  • 它是连接Java应用程序和关系数据库的中间件。
  • 它对JDBC API进行了封装,负责Java的持久化。
  • 在分层软件架构中它位于持久化层,封装了所有数据访问细节,使业务逻辑层可以专注与实现业务逻辑。
  • 它是一只ORM映射工具,能够建立面向对象的域模型和关系数据模型之间的映射。

本章介绍软件的三种模型:概念模型、域模型和数据模型,然后介绍了Java对象的持久化概念,并介绍了实现对象持久化的几种模式:

  • 业务逻辑和数据访问耦合
  • 主动域对象模式
  • ORM模式
  • JDO模式
  • CMP模式

应用程序的分层体系结构

四层结构应用软件的结构。

  • 表述层:提供与用户交互的界面。GUI(图形用户界面)和web页面而是表述层的两个典型的例子。
  • 业务逻辑层:实现各种业务逻辑。例如当用户发出生产订单的请求时,业务逻辑层负责计算的价格、验证订单的信息。
  • 持久层:封装数据访问细节,为业务逻辑提供了面向对象的API
  • 数据库层:负责存放和管理应用的持久性业务数据。例如对于电子商务网站应用,在数据库中保存了客户、订单和商品等业务数据。关系数据库依然是目前最流行的数据库。

软件分层的优点

恰当地为软件分层,将会提高软件的以下性能。

  • 伸缩性:伸缩性指应用程序是否能支持更多的用户。
  • 可维护性:当发生需求变化,只需修改软件的某一部分,不会影响其他部分的代码。层次越多,可维护性也会不断提高,因为修改软件的某一部分的实现,不会影响其它层。
  • 可扩展性:是在现有的系统中增加新功能的难易程度。层数越少,添加新功能就越容易破坏现有的程序结构。层数越多,就可以在每个层次中提供扩展点,不会打破应用的整体框架。
  • 可重复性:程序代码有冗余,同一个程序就能满足多种需求。
  • 可管理性:管理系统的难易程度。将应用程序分为多层后,可以将工作分解给不同的开发小组,从而便于管理。应用越复杂,规模越大,需要的层就越多。

软件分层的缺点

  • 软件分层越多,对软件设计人员的要求就越高。
  • 在设计阶段,必须花时间构思合理的体系结构。
  • 开发流程相对复杂,降低开发效率。

Java应用的持久化层

Hibernate API简介

hibernate中的接口可分为以下几类:

  • 提供访问数据库的操作(如保存、更新、删除和查询对象)的接口。这些接口包括:Session、Transaction和Quer接口。
  • 用于配置Hibernate的接口:Configuration。
  • 回调接口,使应用程序接受Hibernate内部发生的事件,并做出相应的回应。这些接口包括:Interceptor、Lifecycle和Validatable接口。
  • 用于扩展Hibernate的功能的接口,如UserType、CompositeUserType和IdentifierGenerator接口,如果需要的话,应用程序可以扩展这些接口。

Hibernate入门

Hibernate是Java应用和关系型数据库之间的桥梁,内部封装了通过JDBC访问数据库的操作,向上层应用提供了面向对象的数据访问API。在Java应用中使用hibernate包含以下步骤。

  • 创建Hibernate的配置文件。
  • 创建持久化类。
  • 创建对象-关系映射文件。
  • 通过HibernateAPI编写访问数据库的代码。

创建Hibernate的配置文件

hibernate的配置文件中读取了数据库连接的有关信息,有两种形式:一种是XML格式文件;还有一种是Java属性文件,采用“健=值”的形式。
配置文件的属性:
hibernate.properties

1
2
3
4
5
6
hibernate.dialect=net.sf.hibernate.dialect.MySQLDialct //指定数据库使用SQL方言
hibernate.connection.driver_class=com.mysql.jdbc.Driver //指定数据库的驱动程序
hibernate.connection.url=jdbc:mysql://localhost:3306/SAMPLEDB //指定数据库的URL
hibernate.connection.username=root //指定数据库的连接名
hibernate.connection.password=root //指定数据库的口令
hibernate.show_sql=ture //是否在控制台输出SQL语句

创建持久化类

持久化类是指其实例需要被Hibernate持久化到数据库中的类。持久化类通常都是域模型中的实体域类。持久化类符合JavaBean的规范,包含一些属性,以及与之对应的getXXX()和setXXX()方法。下列中定义了一个名为Customer的持久化类。

1
2
3
4
5
6
7
8
9
package mypack;
import java.io.Serializable;
import java.sql.Date;
import java.sql.Timestamp;
public class Customer implements Serializable {
-
}

持久化类符合JavaBean的规范,包含一些属性,以及与之对应的getXXX()和setXXX()方法。getXXX()和setXXX()方法必须符合特定的命名规范,”get”和”set”后面紧跟属性的名字,并且属性名的首字母为大写,例如name属性的getName(),如果把get方法写为getname()或者getNANE(),会导致Hibernate在运行时抛出以下的异常:

1
net.sf.hibernate.PropertNotFountException:Could not find a getter for property name in class mypack.Customer

如果为boolean类型可以用isXXX()或者getXXX().
Hibernate并不要求持久化类必须实现java.io.Serializable接口,但是对于采用分布式结构的Java应用,当Java对象在不同的进程点之间传输时,这个对象所属的类必须实现Serializable接口,此外,在Java web应用中,如果希望对HttpSession中存放的Java对象进行持久化,那么这个Java对象所属的类也必须实现Serializable接口。
Customer持久化类有一个id属性,用来唯一标识Customer类的每个属性。在面向对象术语中,这个id属性称为对象标识符(OID,Object Identifier)。通常为整数也可以为其他类型。
Hibernate要求持久化类必须提供一个不带参数的默认构造方法,在程序运行时,Hibernate运用Java反射机制,调用java.lang.reflenct.Constructor.newInstance()方法来构造持久化的实例。如果对这个持久化类使用延迟检索策略,为了使Hibernate能够在运行时为这个持久化类创建动态代理,要求持久化类的默认构造方法的访问级别必须是public或protected类型,而不是default 或private类型。
在Customer类中没有引入任何Hibernate API,Customer类不需要继承Hibernate的类或者实现Hibernate的接口,这提高了持久化类的独立性。

创建数据库Schema

下面为Customer类对应的数据库表名为CUSTOMERS,它在MySQL数据库中的DDL定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
create table CUSTOMERS(
ID bigint not null primary key,
NAME varchar(15) not null,
EMAIL varchar(128) not null,
PASSWORD varchar(8) not null,
PHONE int,
ADDRESS varchar(255),
SEX char(1),
IS_MARRIED bit,
DESCRIPTION text,
IMAGE blob,
BIRTHDAY date,
REGISTERED_TIME timestamp
);

创建对象-关系映射文件

Hibernate采用XML格式的文件来指定对象和关系数据之间的映射。在运行时,Hibernate将根据这个映射文件来生成各种SQL语句。下面的Customer.hbm.xml把Customer类映射到CUSTOMERS表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="mypack.Customer" table="CUSTOMERS">
<id name="id" column="ID" type="long"><generator class="increment"/></id>
<property name="name" column="NAME" type="string" not-null="true"/>
<property name="email" column="EMAIL" type="string" not-null="true"/>
<property name="password" column="PASSWORD" type="string" not-null="true"/>
<property name="phone" column="PHONE" type="int"/>
<property name="address" column="ADDRESS" type="string"/>
<property name="sex" column="SEX" type="character"/>
<property name="married" column="IS_MARRIED" type="boolean"/>
<property name="description" column="DESCRIPTION" type="text"/>
<property name="image" column="IMAGE" type="binary"/>
<property name="birthday" column="BIRTHDAY" type="date"/>
<property name="registeredTime" column="REGISTEREDTIME" type="timestamp"/>
</class>
</hibernate-mapping>

映射文件的文档类型定义(DTD)

Customer.hbm.xml文件的开头定义声明DTD(Document Type Definition,文档类型定义),它对XML文件的语法和格式做了定义。

Adhere to the original technology to share, your support will encourage me to continue to create!