使用Hibernate完成对象持久化
一、 为什么要使用Hibernate
先来回顾一下以前通过DAO怎么操作数据库。
增加学生信息:
public int addStudent(Student stu) { Connection con = null; PreparedStatement pstmt = null; int rowCount = 0;
try { con = DBUtil.getCon(); String sql = "insert into Student values(?, ?, ?, ?, ?)"; pstmt = con.prepareStatement(sql); pstmt.setString(1, stu.getStuName()); pstmt.setString(2, stu.getStuPwd()); pstmt.setInt(3, stu.getStuAge()); pstmt.setInt(4, stu.getStuSex()); pstmt.setString(5, stu.getStuAddr());
rowCount = pstmt.executeUpdate(); //执行更新 } catch (Exception ex) { ex.printStackTrace(); } finally { DBUtil.closeDB(null, pstmt, con); }
return rowCount; }
|
查询学生信息:
public List<Student> findAllStudent() { Connection con = null; PreparedStatement pstmt = null; ResultSet rs = null; List<Student> stuList = null;
try { con = DBUtil.getCon(); String sql = "select * from Student"; pstmt = con.prepareStatement(sql); rs = pstmt.executeQuery(); stuList = new ArrayList<Student>();
while(rs.next()) { Student stu = new Student(); stu.setSid(rs.getInt("sid")); stu.setStuName(rs.getString("stuName")); stu.setStuPwd(rs.getString("stuPwd")); stu.setStuAge(rs.getInt("stuAge")); stu.setStuSex(rs.getInt("stuSex")); stu.setStuAddr(rs.getString("stuAddr"));
stuList.add(stu); } } catch (Exception ex) { ex.printStackTrace(); } finally { DBUtil.closeDB(rs, pstmt, con); }
return stuList; } |
修改学生信息:
public int updateStudent(Student stu) { Connection con = null; PreparedStatement pstmt = null; int rowCount = 0;
try { con = DBUtil.getCon(); String sql = "update Student set stuName = ?, stuPwd = ?, stuAge = ?, stuSex = ?, stuAddr = ? where sid = ?"; pstmt = con.prepareStatement(sql); pstmt.setString(1, stu.getStuName()); pstmt.setString(2, stu.getStuPwd()); pstmt.setInt(3, stu.getStuAge()); pstmt.setInt(4, stu.getStuSex()); pstmt.setString(5, stu.getStuAddr()); pstmt.setInt(6, stu.getSid());
rowCount = pstmt.executeUpdate(); //执行更新 } catch (Exception ex) { ex.printStackTrace(); } finally { DBUtil.closeDB(null, pstmt, con); }
return rowCount; } |
通过以上的代码,我们可以看出,按照以前的方式操作数据库,代码烦琐且容易出错。而且很多代码都基本上是重复的,所以纯“体力”性劳动充斥在我们的开发中,花去了我们大部分的开发时间。
自然的,我们不禁要问,有没有一种方案来解决这个问题,让我们可以早日从这些纯“体力性”的劳动中解放出来,而把绝大部分时间花在系统的业务逻辑上呢。正是在这样的背景下,Hibernate应运而生了,它的出现给Java程序员带来了福音。
二、 Hibernate是什么
接下来,我们一起学习关于Hibernate的一些基本概念。
Hibernate:Hibernate是一个基于JDBC的主流持久化框架,它提供了对JDBC的薄层封装。它是一个优秀的ORM实现。使用Hibernate,通过对对象的操作就可以完成对关系型数据库的操作。 |
程序中数据的两种状态:
l 瞬时状态:保存在内存中的程序数据,程序退出后,数据就消失了,称为瞬时状态。
l 持久状态:保存在磁盘上的程序数据,程序退出后依然存在,称为程序数据的持久状态。
有的时候,我们需要对程序中的数据在这两种状态之间进行转换。比如,当用户注册的时候,就需要把数据从内存中写到数据库中,这个时候就是将程序中的数据由瞬时状态转变持久状态。又比如,当用户登陆某个在线商店,想要查看该商店的所有商品,这个时候需要将数据库中的所有商品数据查询到内存中,显示给客户。这个时候就是将程序中的数据由 持久状态转变成瞬时状态。由此,我们引入持久化的概念:
持久化:将程序数据在瞬时状态和持久状态进行转换的机制。 |
以前我们是通过JDBC进行数据持久化的。比如如下代码:
瞬时状态 à 持久状态(内存中 à 数据库中)
pstmt = con.prepareStatement(sql); pstmt.setString(1, stu.getStuName()); pstmt.setString(2, stu.getStuPwd()); pstmt.setInt(3, stu.getStuAge()); pstmt.setInt(4, stu.getStuSex()); pstmt.setString(5, stu.getStuAddr()); rowCount = pstmt.executeUpdate(); |
持久状态 à 瞬时状态 (数据库中 à 内存中)
while(rs.next()) { Student stu = new Student(); stu.setSid(rs.getInt("sid")); stu.setStuName(rs.getString("stuName")); stu.setStuPwd(rs.getString("stuPwd")); stu.setStuAge(rs.getInt("stuAge")); stu.setStuSex(rs.getInt("stuSex")); stu.setStuAddr(rs.getString("stuAddr")); stuList.add(stu); } |
我们发现,如果数据库中表的字段比较多的话,这个工作量是很大的,通过Hibernate,可以极大的简化该代码。
ORM:Object Relation Mapping(对象关系映射)。
程序语言发展至今,我们多以面向对象的形式来组织整个程序。处于瞬时状态的数据主要以对象的形式保存在内存中,而处于持久状态的数据很多时候都是保存在关系型数据库中。所以,通常情况下,持久化要完成的操作就是把对象(Object)保存到关系型数据库(Relation DataBase)中,或者从关系型数据库中把程序数据取出,然后再以对象的形式进行封装。
ORM:完成对象到关系型数据库的映射机制称为对象—关系映射,简称为ORM |
Hibernate提供了对JDBC的封装。也就是说,我们在使用Hibernate编写程序的时候,只需要对对象进行操作即可,Hibernate会自动的生成相应的SQL语句,完成数据的持久化操作。简而言之,通过Hibernate我们通过对对象的操作完成对关系型数据库的操作。
注意:我们在编写程序的时候,是以对象的形式进行操作。而在保存数据的时候,是保存到关系型数据库的表中。这个时候,我们必须在对象和表之间建立映射关系。否则,Hibernate就不知道我们对某个对象的操作就是对数据库中某张表的操作;我们对对象的属性的操作就是对表的字段的操作。这个映射关系(类ßà表),我们是通过xml的形式进行配置的,也就是我们稍后要讲到的*.hbm.xml文件。
三、 在MeEclipse中使用Hibernate开发应用程序的步骤
准备工作:
1、 在MyEclipse中建立和数据库的连接。
选择透视图
选择数据库浏览器试图
出现的界面如下
在空白区域,右键单击,选择New
出现界面如下,开始配置数据库连接驱动
下面,以连接SQL Server 2000 为例,配置如下
点击下一步,再单击Finish即可,效果如下
右键单击,选择Open Connection
展开其中的节点,如下效果
2、 在工程中导入Hibernate的支持库文件
切换到MyEclipse视图中,为工程添加Hibernate支持
注意要选中JAR Library Installation的第二个单选按纽
单击下一步,再单击下一步,为该工程选择连接数据库的驱动配置
单击下一步,不用选中创建SessionFactory类
最后选中Finish即可。
3、 生成Hibernate的配置文件(hibernate.cfg.xml)
hibernate.cfg.xml
<?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<!-- Generated by MyEclipse Hibernate Tools. --> <hibernate-configuration>
<session-factory> <!-- 驱动类 --> <property name="connection.driver_class"> com.microsoft.jdbc.sqlserver.SQLServerDriver </property>
<!-- URL --> <property name="connection.url"> jdbc:microsoft:sqlserver://localhost:1433 </property>
<!-- 用户名 --> <property name="connection.username">sa</property>
<!-- 数据库方言:SQL Server --> <property name="dialect"> org.hibernate.dialect.SQLServerDialect </property>
<property name="myeclipse.connection.profile">sql</property>
<!-- 显示SQL语句 --> <property name="show_sql">true</property>
</session-factory>
</hibernate-configuration> |
4、 生成POJO类和相应的映射文件(*.hbm.xml)
Student.java
package com.westaccp.hibernate.entity;
/** * Student entity. * * @author MyEclipse Persistence Tools */
public class Student implements java.io.Serializable {
// Fields
private Integer sid; private String stuName; private String stuPwd; private Integer stuAge; private Byte stuSex; private String stuAddr;
// Constructors
/** default constructor */ public Student() { }
/** minimal constructor */ public Student(String stuName, String stuPwd) { this.stuName = stuName; this.stuPwd = stuPwd; }
/** full constructor */ public Student(String stuName, String stuPwd, Integer stuAge, Byte stuSex, String stuAddr) { this.stuName = stuName; this.stuPwd = stuPwd; this.stuAge = stuAge; this.stuSex = stuSex; this.stuAddr = stuAddr; }
// Property accessors
public Integer getSid() { return this.sid; }
public void setSid(Integer sid) { this.sid = sid; }
public String getStuName() { return this.stuName; }
public void setStuName(String stuName) { this.stuName = stuName; }
public String getStuPwd() { return this.stuPwd; }
public void setStuPwd(String stuPwd) { this.stuPwd = stuPwd; }
public Integer getStuAge() { return this.stuAge; }
public void setStuAge(Integer stuAge) { this.stuAge = stuAge; }
public Byte getStuSex() { return this.stuSex; }
public void setStuSex(Byte stuSex) { this.stuSex = stuSex; }
public String getStuAddr() { return this.stuAddr; }
public void setStuAddr(String stuAddr) { this.stuAddr = stuAddr; }
} |
Student.hbm.xml
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Mapping file autogenerated by MyEclipse Persistence Tools --> <hibernate-mapping> <!-- name:指定类名 table:指定表名 --> <class name="com.westaccp.hibernate.entity.Student" table="Student" schema="dbo" catalog="master"> <!-- 主键配置:name:在类中属性名 type:属性数据类型 --> <id name="sid" type="java.lang.Integer"> <!-- name:对应的数据库表字段名 --> <column name="sid" /> <!-- 主键生成策略 --> <generator class="native"></generator> </id> <!-- 配置属性:name:在类中属性名 type:属性数据类型 --> <property name="stuName" type="java.lang.String"> <!-- 配置字段:name:指定字段名 length:字段程度 not-null:是否非空 --> <column name="stuName" length="30" not-null="true" /> </property> <property name="stuPwd" type="java.lang.String"> <column name="stuPwd" length="30" not-null="true" /> </property> <property name="stuAge" type="java.lang.Integer"> <column name="stuAge" /> </property> <property name="stuSex" type="java.lang.Byte"> <column name="stuSex" /> </property> <property name="stuAddr" type="java.lang.String"> <column name="stuAddr" length="50" /> </property> </class> </hibernate-mapping>
|
此时,hibernate.cfg.xml配置多了如下一行
<mapping resource="com/westaccp/hibernate/entity/Student.hbm.xml" /> |
编写代码:
1、 得到配置对象Configuration
Configuration config = new Configuration().configure(); |
2、 得到Session工厂SessionFactory
SessionFactory factory = config.buildSessionFactory(); |
3、 通过Session工厂得到Session
Session session = factory.openSession(); |
4、 开始事务
tx = session.beginTransaction(); |
5、 持久化操作
session.save(stu); |
6、 提交事务
tx.commit(); |
7、 关闭Session
session.close(); |
完整代码如下:
public void addStudent(Student stu) { Configuration config = new Configuration().configure(); SessionFactory factory = config.buildSessionFactory(); Session session = factory.openSession(); Transaction tx = null;
try { tx = session.beginTransaction(); session.save(stu); tx.commit(); } catch (Exception ex) { if(tx != null) { tx.rollback(); } ex.printStackTrace(); } finally { session.close(); } } |