昨晚喝多了,下午刚清醒,继续搞Hibernate。走起、 java
以为还行的话,记得点赞哈,给我这个渣渣点学习的动力。有错误的话也请指出,省的我在错误上走了不归路。呵呵。程序员
本篇目录:sql
- 数据持久化概念
- Hiberante框架及ORM
2.1. Hibernate框架
2.2. 什么是ORM
2.3. Hibernate框架的优缺点及其适用场合
2.4.1 Hibernate框架的优势
2.4.2 Hibernate框架的缺点
2.4. Hibernate环境搭建
2.5. 技能训练
2.6. 练习
数据持久化是将内存中的数据模型转换为存储模型,以及将存储模型转换为内存中的数据模型的同城。数据库
例如,文件的存储、数据读取等都是数据持久化操做。数据模型能够是任何数据结构或对象模型,存储模型能够是关系模型、XML、二进制流等。编程
从以上的概念描述,咱们思考一下,以前是否接触过数据持久化?是否作过数据持久化的操做?api
答案是确定的。以前一开始,咱们就编写应用程序操做数据表,对数据表进行增删改查的操做,例JDBC/ADO.NET等,即数据持久化。session
而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成为全世界最流行的开源对象关系映射框架。
ORM(Object/Relational Mapping)即对象/关系映射,是一种数据持久化技术。
它在对象模型和关系型数据库之间创建起对应关系,而且提供了一种机制,经过JavaBean对象去操做数据库表中的数据,如图:
ORM映射关系
在实际开发中,程序员使用面向对象的技术操做数据,而当存储数据时,使用的倒是关系型数据库,这样形成了不少不便。
ORM在对象模型和关系数据库的表之间创建了一座桥梁,有了ORM,程序员就不须要再使用SQL语句操做数据库中的表,使用API直接操做JavaBean对象就能够实现数据的存储、查询、更改和删除等操做。
Hibernate就是采用ORM对象关系映射技术的持久化开发框架。
回顾一下DAO层代码,以查找全部用户为例,直接使用JDBC查询用户的代码以下:
1 List users = new ArrayList(); 2 User user; 3 Connection conn = null; 4 Statement stmt = null; 5 ResultSet rs = null; 6 try{ 7 conn = DBUtil.getConnection(); 8 stmt = conn.createStatement(); 9 rs = stmt.executeQuery("select * rom users"); 10 while(rs.next()){ 11 user = new User(); 12 user.setId(rs.getInt("Id")); 13 user.setUsername(rs.getString("Username")); 14 user.setPassword(rs.getString("Password")); 15 user.setTelephone(rs.getString("Telephone")); 16 user.setRegisterDate(rs.getDate("RegisterDate")); 17 user.setSex(rs.getInt("Sex")); 18 users.add(user); 19 } 20 }catch(Exception e){ 21 e.printStackTrace(); 22 }finally{ 23 DBUtil.close(rs,stmt,conn); 24 }
用JDBC查询返回的是ResultSet对象,ResultSet每每并不能直接使用,还须要转换成List,而且经过JDBC查询不能直接获得具体的业务对象。
这样在整个查询的过程当中,就须要作不少重复性的转换工做。
使用Hibernate完成持久化操做,只须要编写以下代码:
1 Session session = HibernateUtil.getSession(); 2 Query query = session.createQuery("from User"); 3 List<User> users = (List<User>)query.list();
HibernateUtil是一个自定义的工具类,用于获取Session对象。
Hibernate处理数据库查询时,编写的代码很是简洁。Hibernate直接返回的是一个List集合类型的对象,能够直接使用。这样就避免了繁琐的重复性的数据转换过程。
(1)功能强大,是Java应用与关系数据库之间的桥梁,较之JDBC方式操做数据库,代码量大大减小,提升了持久化代码的开发速度,下降了维护成本;
(2)Hibernate支持许多面向对象的特性,如组合、继承、多态等,使得开发人员没必要在面向业务领域的对象模型和面向数据库的关系数据库之间模型之间来回切换,方便开发人员进行领域驱动的面向对象的设计与开发;
(3)可移植性好。系统不会绑定在某个特定的关系型数据库上,对于系统更换数据库,一般只须要修改Hibernate配置文件便可正常运行;
(4)Hibernate框架免费,能够在须要时研究源代码,改写源代码,进行功能的定制,具备可扩展性。
Hibernate适用于大中型项目。
(1)不适合以数据为中心大量使用存储过程的应用;
(2)大规模的批量插入、修改和删除不适合用Hibernate。
Hibernate不适用于小型项目,也不适用于关系模型设计不合理、不规范的系统。
在MyEclipse中新建工程后,使用Hibernate,须要作如下准备工做:
下载Jar包 -> 部署Jar包 -> 建立配置文件(hibernate.cfg.xml) -> 建立持久化类和映射文件 |
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 | 日志输出 |
具体步骤以下:
(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-3.6.10.Final-dist/project/hibernate-core/src/main/java
而后点击“OK”即设置完成。
Hibernate配置文件主要用于配置数据库链接和Hibernate运行时所须要的各类特性。
在工程的src目录下添加Hibernate配置文件(可在hibernate-distribution-3.6.10.Final-dist.zip的project\etc目录下找到示例文件)。
默认文件名为“hibernate.cfg.xml”,该文件须要配置数据库链接信息和Hibernate的参数,以下代码所示。
1 <!DOCTYPE hibernate-configuration PUBLIC 2 "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 3 "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> 4 5 <hibernate-configuration> 6 <session-factory> 7 <!-- 数据库JDBC驱动 --> 8 <property name="connection.driver_class">com.microsoft.sqlserver.jdbc.SQLServerDriver</property> 9 <!-- 数据库URL --> 10 <property name="connection.url">jdbc:sqlserver://182.92.215.126:1433;databaseName=HibernateStudy</property> 11 <!-- 数据库用户 --> 12 <property name="connection.username">sa</property> 13 <!-- 数据库密码 --> 14 <property name="connection.password">NbNjC586546mssql</property> 15 16 <!-- 每一个数据库都有其对应的Dialect以匹配平台特性 --> 17 <property name="dialect">org.hibernate.dialect.SQLServer2008Dialect</property> 18 19 <!-- 指定当前session范围和上下文 --> 20 <property name="current_session_context_class">thread</property> 21 22 <!-- 是否将运行时生成的SQL输出到日志以供调试 --> 23 <property name="show_sql">true</property> 24 25 <!-- 是否格式化SQL --> 26 <property name="format_sql">true</property> 27 28 <!-- 默认状况下是auto的,就是说若是不设置的话它是会自动去你的classpath下面找一个bean-validation**包,可是找不到,因此会出现Bean Valition Factory错误。 --> 29 <property name="javax.persistence.validation.mode">none</property> 30 </session-factory> 31 </hibernate-configuration>
其中几个经常使用参数的做用以下:
(1)connection.url:表示数据库URL。“jdbc:sqlserver://182.92.215.126:1433;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、DB二、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中的部门表为例。
持久化类是指其实例状态须要被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代码以下:
1 package com.geeksss.HibernateStudy.entity; 2 3 import java.io.Serializable; 4 5 /** 6 * 部门实体类 7 * @author 张董 8 */ 9 public class Dept implements Serializable{ 10 // Field 11 private int deptNo; 12 private String deptName; 13 private String location; 14 15 // Structure 16 public Dept(){} 17 18 // Getter and Setter 19 public int getDeptNo() { 20 return deptNo; 21 } 22 23 public void setDeptNo(int deptNo) { 24 this.deptNo = deptNo; 25 } 26 27 public String getDeptName() { 28 return deptName; 29 } 30 31 public void setDeptName(String deptName) { 32 this.deptName = deptName; 33 } 34 35 public String getLocation() { 36 return location; 37 } 38 39 public void setLocation(String location) { 40 this.location = location; 41 } 42 }
Dept持久化类有一个deptNo属性,用来惟一标识Dept类的每一个对象。deptNo属性又称为id属性。
在Hibernate中,这个id属性被称为对象标识符(OID,Object Identifier)。一个Dept对象和数据库中Dept表中的一条记录对应。
建立持久化类后,还须要“告诉”Hibernate,持久化类Dept映射到数据库的哪一个表,以及哪一个属性对应数据库表的哪一个字段,这些都要在映射文件Dept.hbm.xml中配置。
详细的映射文件代码以下(注意:在Hibernate中,映射文件一般以“.hbm.xml”做为后缀。):
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 5 6 <hibernate-mapping> 7 <class name="com.geeksss.HibernateStudy.entity.Dept" table="Dept"> 8 <id name="deptNo" type="java.lang.Integer" column="DeptNo"> 9 <generator class="assigned"></generator> 10 </id> 11 <property name="deptName" type="java.lang.String" column="DeptName"></property> 12 <property name="location" type="java.lang.String"> 13 <column name="Location"></column> 14 </property> 15 </class> 16 </hibernate-mapping>
上述示例代码Dept.hbm.xml是Dept类到数据库表Dept的映射,其中各元素的含义以下:
经常使用的主键生成策略以下:
(1)increment:对类型long、short或int的主键,以自动增加的方式生成主键的值。主键按数值顺序递增,增量为1;
(2)identity:对如SQL Server、DB二、MySQL等支持标识列的数据库,可以使用该主键生成策略生成自动增加主键,但要在数据中将该主键设置为标识列;
(3)sequence:对如Oracle、DB2等支持序列的数据库,可以使用该主键生成策略生成自动增加主键,经过子元素param传入数据库中序列的名称;
(4)native:由Hibernate根据底层数据库自行判断采用何种生成策略,即由使用的数据库生成主键的值;
(5)assigned:主键由应用程序负责生成,无需Hibernate参与。
映射信息在映射文件中定义,还须要在配置文件hibernate.cfg.xml中声明,如:
1 <!DOCTYPE hibernate-configuration PUBLIC 2 "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 3 "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> 4 5 <hibernate-configuration> 6 <session-factory> 7 <!-- 在此省略以前的其余配置 --> 8 9 <!-- 映射文件配置,注意配置文件名必须包含其相对于classpath的全路径 --> 10 <mapping resource="com/geeksss/HibernateStudy/mapping/Dept.hbm.xml"/> 11 </session-factory> 12 </hibernate-configuration>
经过前面的学习,了解了Hibernate框架,并学习如何搭建Hibernate环境。接下来为租房系统搭建Hibernate环境。
从本节起,使用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写好了,你们拿过去直接运行便可(没错 我就是雷锋 雷锋就是我):
1 use HibernateStudy 2 go 3 4 -- 用户表结构 5 if exists(select * from sys.tables where name='Users') drop table Users 6 go 7 create table Users 8 ( 9 Id int primary key identity(1,1) not null, -- 用户编号 10 Name nvarchar(50) not null, -- 用户名 11 Password nvarchar(50) not null, -- 密码 12 Telephone nvarchar(15) not null, -- 电话 13 Username nvarchar(50) not null, -- 姓名 14 IsAdmin bit default(0) null -- 是不是管理员 15 ) 16 go 17 18 -- 房屋类型表 19 if exists(select * from sys.tables where name='Type') drop table Type 20 go 21 create table Type 22 ( 23 Id int primary key identity(1,1) not null, -- 类型编号 24 Name nvarchar(50) not null -- 类型名称 25 ) 26 go 27 28 -- 区县信息表 29 if exists(select * from sys.tables where name='District') drop table District 30 go 31 create table District 32 ( 33 Id int primary key identity(1,1) not null, -- 区县编号 34 Name nvarchar(50) not null -- 区县名称 35 ) 36 go 37 38 -- 区县信息表 39 if exists(select * from sys.tables where name='Street') drop table Street 40 go 41 create table Street 42 ( 43 Id int primary key identity(1,1) not null, -- 街道编号 44 Name nvarchar(50) not null, -- 街道名称 45 DistrcitId int foreign key(Id) references District -- 区县编号,外键引用区县表主键 46 ) 47 go 48 49 if exists(select * from sys.tables where name='Hourse') drop table Hourse 50 go 51 create table Hourse 52 ( 53 Id int primary key identity(1,1) not null, -- 房屋信息编号 54 Title nvarchar(50) not null, 55 Description nvarchar(2000) not null, 56 Price money not null, 57 PublishDate date default(getdate()) null, 58 FloorAge int not null, 59 Contact nvarchar(100) not null, 60 UserId int foreign key(Id) references Users, 61 TypeId int foreign key(Id) references Type, 62 StreetId int foreign key(Id) references Street 63 ) 64 go 65 66 67 -- 向房屋类型表插入数据 68 insert into Type(Name) 69 select '单人间' union 70 select '双人间' union 71 select '豪华套间' 72 73 -- 向区县表插入数据 74 insert into District(Name) 75 select '海淀区' union 76 select '昌平区' union 77 select '朝阳区' union 78 select '大兴区' 79 80 -- 向街道表插入数据 81 insert into Street(Name,DistrcitId) 82 select '清河天兰尾货',1 union 83 select '沙河镇沙阳路',2 union 84 select '北皋北京机场',3 union 85 select '亦庄火车站',4 86 87 -- 向用户信息表中插入数据 88 insert into Users(Name,Password,Telephone,Username,IsAdmin) 89 select '张董','zd123456','18600807420','ZhangDong',1 union 90 select '兵哥','bg123456','13800138000','SunHongYu',0 union 91 select '老刘','ll123456','13800138001','LiuQinYi',0 union 92 select 'lisir','ls123456','13800138002','LiJunZhi',0 93 94 -- 向房屋信息表中插入数据 95 insert into Hourse(Title,Description,Price,PublishDate,FloorAge,Contact,UserId,TypeId,StreetId) 96 select '精装单人间出租','电视有线网线等包罗万象',500,convert(date,'2015-09-01'),20,'张先生',1,1,2 union 97 select '豪华套间招租','豪华让你没的说 看了就爱上',1500,convert(date,'2015-09-02'),40,'孙老板',2,3,1 union 98 select '双人间火热出租','别说两我的 两个半我的也够住 哈哈',800,convert(date,'2015-09-03'),30,'李先生',3,2,3
为租房系统搭建Hibernate环境。
(1)在MyEclipse中建立工程,导入Hibernate的jar包;
(2)建立Hibernate配置文件hibernate.cfg.xml;
(3)建立用户表对应的持久化类User和映射文件User.hbm.xml;
(4)在hibernate.cfg.xml中声明上面的映射文件。
在这里,咱们只须要完成上述4个步骤,至于CDUR(增删改查)的操做,下节我们继续。
你们照着上面的步骤,本身练习去吧。吼吼。
有问题留言,有错误也请你们指出。