引导目录:
昨晚喝多了,下午刚清醒,继续搞Hibernate。走起、
觉得还行的话,记得点赞哈,给我这个渣渣点学习的动力。有错误的话也请指出,省的我在错误上走了不归路。呵呵。
本篇目录:
- 数据持久化概念
- Hiberante框架及ORM2.1. Hibernate框架
2.2. 什么是ORM
2.3. Hibernate框架的优缺点及其适用场合 2.4.1 Hibernate框架的优点
2.4.2 Hibernate框架的缺点
2.4. Hibernate环境搭建
2.5. 技能训练
2.6. 练习
1.数据持久化概念
数据持久化是将内存中的数据模型转换为存储模型,以及将存储模型转换为内存中的数据模型的同城。
例如,文件的存储、数据读取等都是数据持久化操作。数据模型可以是任何数据结构或对象模型,存储模型可以是关系模型、XML、二进制流等。
从以上的概念描述,我们思考一下,之前是否接触过数据持久化?是否做过数据持久化的操作?
答案是肯定的。之前一开始,我们就编写应用程序操作数据表,对数据表进行增删改查的操作,例JDBC/ADO.NET等,即数据持久化。
而Hibernate和数据持久化有什么关系嘞?
2.Hibernate框架及ORM
2.1 Hibernate框架
Hibernate是数据持久化工具,是一个开放源代码的对象关系映射框架。
Hibernate内部封装了通过JDBC访问数据库的操作,向上层应用提供面向对象的数据访问API。
Gavin King是Hibernate的创始人,EJB3.0专家委员会成员,JBoss核心成员之一,也是《Hibernate in Action》一书的作者。
2011年,Gavin King使用EJB的Entity bean 1.1时,觉得开发效率太低,试图寻找更好的方案。
经过两年多的努力,在2003年,Gavin King和他的开发团队推出了Hibernate。
Gavin King成为全世界JavaEE数据库解决方案的领导者,Hibernate成为全世界最流行的开源对象关系映射框架。
2.2 什么是ORM
ORM(Object/Relational Mapping)即对象/关系映射,是一种数据持久化技术。
它在对象模型和关系型数据库之间建立起对应关系,并且提供了一种机制,通过JavaBean对象去操作数据库表中的数据,如图:
ORM映射关系
在实际开发中,程序员使用面向对象的技术操作数据,而当存储数据时,使用的却是关系型数据库,这样造成了很多不便。
ORM在对象模型和关系数据库的表之间建立了一座桥梁,有了ORM,程序员就不需要再使用SQL语句操作数据库中的表,使用API直接操作JavaBean对象就可以实现数据的存储、查询、更改和删除等操作。
Hibernate就是采用ORM对象关系映射技术的持久化开发框架。
2.3 Hibernate框架的优缺点及其适用场合
回顾一下DAO层代码,以查找所有用户为例,直接使用JDBC查询用户的代码如下:
List users = new ArrayList(); User user; Connection conn = null; Statement stmt = null; ResultSet rs = null; try{ conn = DBUtil.getConnection(); stmt = conn.createStatement(); rs = stmt.executeQuery("select * rom users"); while(rs.next()){ user = new User(); user.setId(rs.getInt("Id")); user.setUsername(rs.getString("Username")); user.setPassword(rs.getString("Password")); user.setTelephone(rs.getString("Telephone")); user.setRegisterDate(rs.getDate("RegisterDate")); user.setSex(rs.getInt("Sex")); users.add(user); } }catch(Exception e){ e.printStackTrace(); }finally{ DBUtil.close(rs,stmt,conn); }
用JDBC查询返回的是ResultSet对象,ResultSet往往并不能直接使用,还需要转换成List,并且通过JDBC查询不能直接得到具体的业务对象。
这样在整个查询的过程中,就需要做很多重复性的转换工作。
使用Hibernate完成持久化操作,只需要编写如下代码:
Session session = HibernateUtil.getSession(); Query query = session.createQuery("from User"); List<User> users = (List<User>)query.list();
HibernateUtil是一个自定义的工具类,用于获取Session对象。
Hibernate处理数据库查询时,编写的代码非常简洁。Hibernate直接返回的是一个List集合类型的对象,可以直接使用。这样就避免了繁琐的重复性的数据转换过程。
2.3.1 Hibernate框架的优点
(1)功能强大,是Java应用与关系数据库之间的桥梁,较之JDBC方式操作数据库,代码量大大减少,提高了持久化代码的开发速度,降低了维护成本;
(2)Hibernate支持许多面向对象的特性,如组合、继承、多态等,使得开发人员不必在面向业务领域的对象模型和面向数据库的关系数据库之间模型之间来回切换,方便开发人员进行领域驱动的面向对象的设计与开发;
(3)可移植性好。系统不会绑定在某个特定的关系型数据库上,对于系统更换数据库,通常只需要修改Hibernate配置文件即可正常运行;
(4)Hibernate框架免费,可以在需要时研究源代码,改写源代码,进行功能的定制,具有可扩展性。
Hibernate适用于大中型项目。
2.3.1 Hibernate框架的缺点
(1)不适合以数据为中心大量使用存储过程的应用;
(2)大规模的批量插入、修改和删除不适合用Hibernate。
Hibernate不适用于小型项目,也不适用于关系模型设计不合理、不规范的系统。
2.4 Hibernate环境搭建
在MyEclipse中新建工程后,使用Hibernate,需要做以下准备工作:
下载Jar包 -> 部署Jar包 -> 创建配置文件(hibernate.cfg.xml) -> 创建持久化类和映射文件 |
2.4.1 下载需要的jar包
Hibernate的官方网站是http://www.hibernate.org,Hibernate的jar包都可以从官方网站上下载得到。
为了方便新手下载,在此我整理了一下,附上下载地址:http://www.geeksss.com/thread-169-1-1.html。
目前最新版本是5.0.1.FINAL,推荐新手学习使用“hibernate-distribution-x.x.x.GA-dist.zip”。
在这里我用的是“hibernate-distribution-3.6.10.Final-dist”。解压后目录结构如下:
注意根目录和lib\required目录。
根目录包含文件夹和文件,在根目录下存放着hibernate3.jar,Hibernate的接口和类就在这个Jar包中。
Hibernate会使用到一些第三方类库,这些类库放在了lib\required目录下:
名称 | 说明 |
antlr-2.7.6.jar | 语法分析器 |
commons-collections-3.1.jar | 各种集合和集合工具类的封装 |
dom4j-1.6.1.jar | XML的读写 |
javassist-3.12.0.GA.jar | 分析、编辑和创建Java字节码的类库 |
jta-1.1.jar | Java事务API |
slf4j-api-1.6.1.jar | 日志输出 |
2.4.2 部署Jar包
具体步骤如下:
(1)将下载的后hibernate3.jar包和lib\required下的jar包及数据库驱动jar包复制到建好的工程WEB-INF下的lib目录中:
(2)通过MyEclipse导入上述的包。在MyEclipse中,选中复制到lib里面的jar包,右键 - “Build Path” - “Add to Build Path”,即可快速添加引用:
在此,如果你需要进行一些其他的配置,而不仅仅是导入jar包,则可以打开详细的对话框进行导入Jar包并设置:
右键项目 - “Build Path” - “Configure Build Path”:
在弹出的窗体中选择“Libraries”选项卡,单击“Add JARs”按钮,如下图,在弹出的“JAR Selection”窗体中选择lib下刚刚复制的jar包,单击OK即可导入:
为了方便学习Hibernate,可以在MyEclipse环境中设置当前工程中的hibernate3.jar的源码。
打开工程,展开“Referenced Libraries”,找到刚刚引入的“hibernate3.jar”,右键,选择“Properties”“:
打开属性窗口之后,在左侧选择”Java Source Attachment”选项,右边选择“External location”,点击“External Floder...”,选择Hibernate中core的源码目录,编码选择项目编码。
例如我的: F:/下载目录/hibernate-distribution-.Final-dist/project/hibernate-core/src/main/java
然后点击“OK”即设置完成。
2.4.3 创建Hibernate配置文件hibernate.cfg.xml
Hibernate配置文件主要用于配置数据库连接和Hibernate运行时所需要的各种特性。
在工程的src目录下添加Hibernate配置文件(可在hibernate-distribution-3.6.10.Final-dist.zip的project\etc目录下找到示例文件)。
默认文件名为“hibernate.cfg.xml”,该文件需要配置数据库连接信息和Hibernate的参数,如下代码所示。
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- 数据库JDBC驱动 --> <property name="connection.driver_class">com.microsoft.sqlserver.jdbc.SQLServerDriver</property> <!-- 数据库URL --> <property name="connection.url">jdbc:sqlserver://182.92.215.126:1433;databaseName=HibernateStudy</property> <!-- 数据库用户 --> <property name="connection.username">sa</property> <!-- 数据库密码 --> <property name="connection.password">NbNjC586546mssql</property> <!-- 每个数据库都有其对应的Dialect以匹配平台特性 --> <property name="dialect">org.hibernate.dialect.SQLServer2008Dialect</property> <!-- 指定当前session范围和上下文 --> <property name="current_session_context_class">thread</property> <!-- 是否将运行时生成的SQL输出到日志以供调试 --> <property name="show_sql">true</property> <!-- 是否格式化SQL --> <property name="format_sql">true</property> <!-- 默认情况下是auto的,就是说如果不设置的话它是会自动去你的classpath下面找一个bean-validation**包,但是找不到,所以会出现Bean Valition Factory错误。 --> <property name="javax.persistence.validation.mode">none</property> </session-factory> </hibernate-configuration>
其中几个常用参数的作用如下:
(1)connection.url:表示数据库URL。“;databaseName=HibernateStudy”是SQL Server数据库的URL。
其中,jdbc:sqlserver://是固定写法,182.92.215.126是数据库的IP地址,1433是SQL Server的端口号,HibernateStudy是连接的目标数据库名称。
(2)connection.driver_class:表示数据库驱动。
"com.microsoft.sqlserver.jdbc.SQLServerDriver"是SQL Server的驱动类。
(3)connection.username:表示数据库用户名。
(4)connection.password:表示数据库用户密码。
(5)dialect:用于配置Hibernate使用的数据库类型。Hibernate支持几乎所有的主流数据库,包括Oracle、DB2、MS SQL Server和MySQL等。
"org.hibernate.dialect.SQLServerDialect"指定当前数据库类型是SQL Server。
(6)current_session_context_class:指定currentSession()方法所得到的Session由谁来跟踪管理。
“thread”指Session由当前线程来跟踪管理。
(7)show_sql:参数为true,则程序运行时在控制台输出SQL语句。
(8)format_sql:参数为true,则程序运行时在控制台输出格式化后的SQL语句。
(9)javax.persistence.validation.mode:默认情况下是auto的,就是说如果不设置的话它是会自动去你的classpath下面找一个bean-validation**包,但是找不到,所以会出现Bean Valition Factory错误。需要设置为none。
资料:
因为Hibernate的配置参数很多,可以在Hibernate资源包“hibernate-distribution-3.6.10.Final-dist\hibernate-distribution-3.6.10.Final\documentation\manual\zh-CN\pdf\”目录中,查看“hibernate_reference.pdf”的第3章,了解Hibernate的可选配置参数。
准备了Hibernate的配置文件hibernate.cfg.xml,接下来就要准备持久化类和映射文件,以SQL Server中的部门表为例。
2.4.4 创建持久化类和映射文件
持久化类是指其实例状态需要被Hibernate持久化到数据库中的类。在应用的设计中,持久化类通常对应需求中的业务实体。
Hibernate对持久化类的要求很少,它鼓励采用POJO编程模型来实现持久化类,与POJO类配合完成持久化工作是Hibernate最期望的工作模式。
Hibernate要求持久化类必须具有一个无参数的构造方法。
POJO(Plain Ordinary Java Object),从字面上来讲就是普通Java对象。
POJO类可以简单地理解为符合JavaBean规范的类,它不需要继承和实现任何特殊的Java基类或者接口。
JavaBean对象的状态保存在属性中,访问属性必须通过对应的getXXX()和setXXX()方法。
下面首先定义部门持久化类,添加一个无参数的构造方法,实现java.io.Serializable接口。
注意,这并不是Hibernate所要求的,如果持久化类有可能放入HttpSession中,就需要实现这个接口。在Web开发中,持久化类放入HttpSession是很常见的。
部门持久化类Dept.java代码如下:
package com.geeksss.HibernateStudy.entity; import java.io.Serializable; /** * 部门实体类 * @author 张董 */ public class Dept implements Serializable{ // Field private int deptNo; private String deptName; private String location; // Structure public Dept(){} // Getter and Setter public int getDeptNo() { return deptNo; } public void setDeptNo(int deptNo) { this.deptNo = deptNo; } public String getDeptName() { return deptName; } public void setDeptName(String deptName) { this.deptName = deptName; } public String getLocation() { return location; } public void setLocation(String location) { this.location = location; } }
Dept.java 部门持久化类
Dept持久化类有一个deptNo属性,用来唯一标识Dept类的每个对象。deptNo属性又称为id属性。
在Hibernate中,这个id属性被称为对象标识符(OID,Object Identifier)。一个Dept对象和数据库中Dept表中的一条记录对应。
创建持久化类后,还需要“告诉”Hibernate,持久化类Dept映射到数据库的哪个表,以及哪个属性对应数据库表的哪个字段,这些都要在映射文件Dept.hbm.xml中配置。
详细的映射文件代码如下(注意:在Hibernate中,映射文件通常以“.hbm.xml”作为后缀。):
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.geeksss.HibernateStudy.entity.Dept" table="Dept"> <id name="deptNo" type="java.lang.Integer" column="DeptNo"> <generator class="assigned"></generator> </id> <property name="deptName" type="java.lang.String" column="DeptName"></property> <property name="location" type="java.lang.String"> <column name="Location"></column> </property> </class> </hibernate-mapping>
Dept.hbm.xml (Dept实体类映射文件)
上述示例代码Dept.hbm.xml是Dept类到数据库表Dept的映射,其中各元素的含义如下:
- class:定义一个持久化类的映射信息。常用属性如下:
- name表示持久化类的全限定名;
- table表示持久化类对应的数据库表名
- schema表示数据库实例中的用户
- id:表示持久化类的OID和表的主键和映射。常用的属性如下:
- name:表示持久化类属性的名称,和属性的访问器相匹配。
- type:表示持久化类属性的类型。
- column:表示持久化类属性对应的数据表字段的名称,也可在子元素column中指定。
- generator:id元素的子元素,用于指定主键的生成策略。常用属性及子元素如下:
- class:用来指定具体主键生成策略。
- param:用来传递参数。上述代码主键生成策略是assigned,不需要配置param元素。
- class:定义一个持久化类的映射信息。常用属性如下:
常用的主键生成策略如下:
(1)increment:对类型long、short或int的主键,以自动增长的方式生成主键的值。主键按数值顺序递增,增量为1;
(2)identity:对如SQL Server、DB2、MySQL等支持标识列的数据库,可使用该主键生成策略生成自动增长主键,但要在数据中将该主键设置为标识列;
(3)sequence:对如Oracle、DB2等支持序列的数据库,可使用该主键生成策略生成自动增长主键,通过子元素param传入数据库中序列的名称;
(4)native:由Hibernate根据底层数据库自行判断采用何种生成策略,即由使用的数据库生成主键的值;
(5)assigned:主键由应用程序负责生成,无需Hibernate参与。
- property:定义持久化类中属性和数据库中表的字段的对应关系。常用属性如下:
- name:表示持久化属性的名称,和属性的访问器相匹配;
- type:表示持久化属性的类型;
- column:表示持久化类属性对应的数据库表字段的名称,也可在子元素column中指定。
- column元素:用于指定其父元素代表的持久化类属性所对应的数据库表中的字段。常用属性如下:
- name:表示字段的名称;
- length:表示字段长度;
- not-null:设定是否可以为null,值为true表示不能为null。
- property:定义持久化类中属性和数据库中表的字段的对应关系。常用属性如下:
映射信息在映射文件中定义,还需要在配置文件hibernate.cfg.xml中声明,如:
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- 在此省略之前的其他配置 --> <!-- 映射文件配置,注意配置文件名必须包含其相对于classpath的全路径 --> <mapping resource="com/geeksss/HibernateStudy/mapping/Dept.hbm.xml"/> </session-factory> </hibernate-configuration>
通过前面的学习,了解了Hibernate框架,并学习如何搭建Hibernate环境。接下来为租房系统搭建Hibernate环境。
2.5 技能训练
租房系统介绍
从本节起,使用Hibernate完成租房系统的各项功能。租房系统是一个B/S架构的信息发布平台。包括两种角色:非注册用户和注册用户。
主要功能如下:
(1)发布房屋信息(注册用户)
(2)浏览房屋信息(注册用户与非注册用户)
(3)查看房屋详细信息(注册用户与非注册用户)
(4)查询房屋信息(注册用户与非注册用户)
(5)修改房屋信息(注册用户)
(6)删除房屋信息(注册用户)
本系统使用SQL Server数据库,请按以下描述创建数据表,如图:
上图描述了租房系统中的五张表,以及它们之间的关系,下面通过表格对这五张表进行说明:
表名:Users(用户表) | |||
字段名 | 字段说明 | 数据类型 | 说明 |
Id | 用户编号 | int | 主键,标识列自动增长 |
Name | 用户名 | nvarchar(50) | 不允许为空 |
Password | 密码 | nvarchar(50) | 不允许为空 |
Telephone | 电话 | nvarchar(15) | 不允许为空 |
Username | 用户名 | nvarchar(50) | 不允许为空 |
IsAdmin | 是否是管理员 | bit | 默认false |
表名:Type(房屋类型表) | |||
字段名 | 字段说明 | 数据类型 | 说明 |
Id | 类型编号 | int | 主键,标识列自增 |
Name | 类型名称 | nvarchar(50) | 不允许为空 |
表名:District(区县表) | |||
字段名 | 字段说明 | 数据类型 | 说明 |
Id | 区县编号 | int | 主键,标识列自增 |
Name | 区县名称 | nvarchar(50) | 不允许为空 |
表名:Street(街道表) | |||
字段名 | 字段说明 | 数据类型 | 说明 |
Id | 街道编号 | int | 主键,标识列自增 |
Name | 街道名称 | nvarchar(50) | 不允许为空 |
DistrictId | 所属区县编号 | int | 外键,引用区县表主键 |
表名:House(房屋信息表) | |||
字段名 | 字段说明 | 数据类型 | 说明 |
Id | 房屋信息编号 | int | 主键,标识列自增 |
Title | 标题 | nvarchar(50) | 不允许为空 |
Description | 描述 | nvarchar(2000) | 不允许为空 |
Price | 出租价格 | money | 不允许为空 |
PublishDate | 发布时间 | date | 默认当前日期 |
FloorAge | 面积 | int | 不允许为空 |
Contact | 联系人 | nvarchar(100) | 不允许为空 |
UserId | 用户编号 | int | 外键,引用用户表主键 |
TypeId | 类型编号 | int | 外键,引用类型表主键 |
StreetId | 街道编号 | int | 外键,引用街道表主键 |
为了方便大家学习,在此我将创建数据表以及插入测试数据的SQL写好了,大家拿过去直接运行即可(没错 我就是雷锋 雷锋就是我):
use HibernateStudy go -- 用户表结构 if exists(select * from sys.tables where name='Users') drop table Users go create table Users ( Id ,) not null, -- 用户编号 Name ) not null, -- 用户名 Password ) not null, -- 密码 Telephone ) not null, -- 电话 Username ) not null, -- 姓名 IsAdmin ) null -- 是否是管理员 ) go -- 房屋类型表 if exists(select * from sys.tables where name='Type') drop table Type go create table Type ( Id ,) not null, -- 类型编号 Name ) not null -- 类型名称 ) go -- 区县信息表 if exists(select * from sys.tables where name='District') drop table District go create table District ( Id ,) not null, -- 区县编号 Name ) not null -- 区县名称 ) go -- 区县信息表 if exists(select * from sys.tables where name='Street') drop table Street go create table Street ( Id ,) not null, -- 街道编号 Name ) not null, -- 街道名称 DistrcitId int foreign key(Id) references District -- 区县编号,外键引用区县表主键 ) go if exists(select * from sys.tables where name='Hourse') drop table Hourse go create table Hourse ( Id ,) not null, -- 房屋信息编号 Title ) not null, Description ) not null, Price money not null, PublishDate date default(getdate()) null, FloorAge int not null, Contact ) not null, UserId int foreign key(Id) references Users, TypeId int foreign key(Id) references Type, StreetId int foreign key(Id) references Street ) go -- 向房屋类型表插入数据 insert into Type(Name) select '单人间' union select '双人间' union select '豪华套间' -- 向区县表插入数据 insert into District(Name) select '海淀区' union select '昌平区' union select '朝阳区' union select '大兴区' -- 向街道表插入数据 insert into Street(Name,DistrcitId) union union union -- 向用户信息表中插入数据 insert into Users(Name,Password,Telephone,Username,IsAdmin) union union union -- 向房屋信息表中插入数据 insert into Hourse(Title,Description,Price,PublishDate,FloorAge,Contact,UserId,TypeId,StreetId) ,,,, union ,,,, union ,,,,
创建表 插入测试数据的SQL
【练习 - 为租房系统搭建Hibernate环境】
需求说明
为租房系统搭建Hibernate环境。
(1)在MyEclipse中创建工程,导入Hibernate的jar包;
(2)创建Hibernate配置文件hibernate.cfg.xml;
(3)创建用户表对应的持久化类User和映射文件User.hbm.xml;
(4)在hibernate.cfg.xml中声明上面的映射文件。
在这里,我们只需要完成上述4个步骤,至于CDUR(增删改查)的操作,下节咱们继续。
大家照着上面的步骤,自己练习去吧。吼吼。
有问题留言,有错误也请大家指出。