Hibernate是持久层的ORM映射框架,专注于数据的持久化工作。所谓的持久化,就是将内存中的数据永久存储到关系型数据库中。
- 主要知识点:
一、什么是Hibernate?
二、如何使用Hibernate?
三、Hibernate的执行过程?如何调用?
四、第一个Hibernate程序
一、什么是Hibernate?
Hibernate是一个开放源代码的ORM框架,它对JDBC进行了轻量级的对象封装,使得Java开发人员可以使用面向对象的编程思想来操作数据库。
ORM:就是利用Java对象与数据库表之间的映射的元数据,实现自动把Java对象持久化到关系型数据库的表中。
ORM原理图
其中,Hibernate框架具有一下优点:
1.对JDBC做了轻量级封装,简化了持久层的代码重复性。
2.是一个优秀的ORM实现,简化了DAO层编码工作。
3.使用Java的反射机制并实现透明性。
4.支持关系型数据库,从一对一到多对多的各种复杂关系。
5.可扩展性强,当功能不够用时,可以自行编码进行扩展。
二、如何使用Hibernate?
步骤1:引入Java包
Hibernate跟Struts一样,都是一套框架,也就是别人已经写好封装好的Java代码。因此,我们要使用Hibernate,就必须引入Hibernate的Jar包。
同理,Jar包统一存放于WEB-INF/lib中。
- 主要的Jar包如下:
§ dom4j(必需):Hibernate在解析XML配置和XML映像元文件时需要使用dom4j。
§ CGLIB(必需):Hibernate在运行时使用这个代码生成库强化类(与Java反射机制联合使用)。
§ Commons Collections, Commons Logging(必需):Hibernat使用Apache Jakarta Commons项目提供的多个工具类库。
§ ODMG4(必需):Hibernate提供了一个可选的ODMG兼容持久化管理界面。如果你需要映像集合,你就需要这个类库,就算你不是为了使用ODMG API。
§ EHCache(必需):Hibernate可以使用不同的第二级Cache方案。如果没有修改配置的话,EHCache提供默认的Cache。
§ Log4j(可选):Hibernate使用Commons Logging API,后者可以使用Log4j作为底层实施log的机制。如果上下文类目录中存在Log4j库,Commons Logging就会使用Log4j和它在上下文类路径中找到的log4j.properties文件。
步骤2:创建实体类(持久化类)
关系型数据库中的表数据要映射成Java对象,必须要有一个对应的与关系表结构一样的实体类,用于存放数据库中取出来的结构化数据。
- 其中,持久化类的编写应该遵循以下规则:
1.持久化类中必须提供无参数public构造器
2.所有属性使用private修饰并提供setter和getter方法
3.必须提供标识OID,与数据库表的主键对应
4.持久化类属性应尽量使用基本数据类型对应的包装类型
5.持久化类不要使用final修饰,否则将无法产生代理对象
步骤3:创建实体类对应的Hibernate映射文件
Hibernate映射文件用于向Hibernate提供,将对象的持久化到关系型数据库中的相关信息,每个映射文件的的结构基本都是相同的,其普遍的代码形式如下:
<?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="XXX" table="xxx">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="XXX" column="xxx" type="string" />
</class>
</hibernate-mapping>
步骤4:Hibernate全局配置文件
同时,跟Struts一样,框架本身需要一个全局配置文件,用于记录调用框架时所需的相关配置信息,例如:数据库服务器地址、数据库名称、数据库管理员账号、密码等。
<?xml version="1.0" encoding="UTF-8"?>
<!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>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///hibernate</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">itcast</property>
<property name="hibernate.show_sql">true</property>
<property name="format_sql">true</property>
<mapping resource="cn/demo/domain/Student.hbm.xml" />
</session-factory>
</hibernate-configuration>
三、Hibernate的执行过程?如何调用?
在Hibernate执行过程中通常会用到5个核心接口,分别为:Configuration接口、SessionFactory接口、Session接口、Transaction接口和Query接口。通过调用这些Hibernate所提供的接口,我们可实现以下调用执行过程:
[Hibernate执行过程.png]
1.Configuration接口
Configuration实例主要用于启动、加载、管理Hibernate的配置文件信息。
//方法一、默认加载src下的hibernate.cfg.xml配置文件
Configuration config = new Configuration().configure();
//方法二、指定路径下加载hibernate.cfg.xml配置文件
Configuration config = new Configuration().configure("xml文件位置");
//方法三、默认加载src目录下hibernate.properties配置文件
Configuration config = new Configuration();
2.SessionFactory接口
SessionFactory接口,负责Hibernate的初始化和建立Session对象。它在Hibernate中起到一个缓冲区作用,Hibernate可以将自动生成的SQL语句、映射数据以及某些可重复利用的的数据放在这个缓冲区中。同时它还保存了对数据库配置的所有映射关系,维护了当前的二级缓存。
- 通常SessionFactory接口会与Configuration实例一起使用,二者结合封装成一个HibernateUtils的工具类。
public class HibernateUtils {
private static final Configuration config;
private static final SessionFactory factory;
static {
config = new Configuration().configure();
factory = config.buildSessionFactory();
}
public static Session getSession() {
return factory.openSession();
}
}
3.Session接口
Session 是应用程序与数据库之间交互操作的一个单线程对象,它的主要功能是为持久化对象提供创建、读取和删除的能力,所有持久化对象必须在session的管理下才可以进行持久化操作。
Session session = sessionFactory.openSession();
Session session = sessionFactory.getCurrentSession();
- 在Session中提供了大量的常用方法,具体如下:
(1)save()、update() 和saveOrUpdate()方法:用于增加和修改对象。
(2)delete()方法:用于删除对象。
(3)get()和load()方法:根据主键查询。
(4)createQuery() 和createSQLQuery()方法:用于数据库操作对象。
(5)createCriteria()方法:条件查询。
4.Transaction接口
Transaction接口主要用于管理事务,它是Hibernate的数据库事务接口,且对底层的事务接口进行了封装。Transaction接口的事务对象是通过Session对象开启的。
Transaction transaction = session.beginTransaction();
调用后,Session执行完数据库操作后,要使用Transaction接口的commit()方法进行事务提交,才能真正的将数据操作同步到数据库中。发生异常时,需要使用rollback()方法进行事务回滚,以避免数据发生错误。因此,在持久化操作后,必须调用Transaction接口的commit()方法和rollback()方法。如果没有开启事务,那么每个Session的操作,都相当于一个独立的操作。
5.Query接口
Query代表面向对象的一个Hibernate查询操作。在Hibernate中,通常使用session.createQuery()方法接受一个HQL语句,然后调用Query的list()或uniqueResult()方法执行查询。所谓的HQL是Hibernate Query Language缩写,其语法很像SQL语法,但它是完全面向对象的。
- 在Hibernate中使用Query对象的步骤,具体所示:
(1)获得Hibernate Session对象。
(2)编写HQL语句。
(3)调用session.createQuery 创建查询对象。
(4)如果HQL语句包含参数,调用Query的setXxx设置参数。
(5)调用Query对象的list() 或uniqueResult() 方法执行查询
6.Criteria接口
Criteria是一个完全面向对象,可扩展的条件查询API,通过它完全不需要考虑数据库底层如何实现,以及SQL语句如何编写,它是Hibernate框架的核心查询对象。Criteria 查询,又称为QBC查询(Query By Criteria),它是Hibernate的另一种对象检索方式。
- 通常,使用Criteria对象查询数据的主要步骤,具体如下:
(1)获得Hibernate的Session对象。
(2)通过Session获得Criteria对象。
(3)使用Restrictions的静态方法创建Criterion条件对象。
(4)向Criteria对象中添加Criterion 查询条件。
(5)执行Criterita的 list() 或uniqueResult() 获得结果。
四、第一个Hibernate程序
1.引入Hibernate的Jar包
引入Hibernate必须的Jar包2.hibernate.cfg.xml
新建Hibernate框架的全局配置文件,用于存放数据库连接字符串等数据库配置信息。
<?xml version="1.0" encoding="UTF-8"?>
<!-- 配制文件的dtd信息 -->
<!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>
<!-- 指定方言 -->
<property name="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</property>
<!--数据库驱动 -->
<property name="hibernate.connection.driver_class">
com.mysql.jdbc.Driver
</property>
<!--连接数据库的url -->
<property name="hibernate.connection.url">
jdbc:mysql:///hibernatedemo
</property>
<!--数据库的用户名 -->
<property name="hibernate.connection.username">
root
</property>
<!--数据库的密码 -->
<property name="hibernate.connection.password">
root
</property>
<!--其它配置 -->
<!-- 显示sql语句 -->
<property name="hibernate.show_sql">true</property>
<!-- 格式化sql语句 -->
<property name="format_sql">true</property>
<!--自动建表 -->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 用来关联hbm配置文件,把所有的实体类映射文件注册进来 -->
<mapping resource="cn/demo/entity/Student.hbm.xml" />
</session-factory>
</hibernate-configuration>
3.Student.java(实体类)
在src下创建cn.demo.entity包,并在里面创建与数据库表一一对应的映射实体类,用于存放从数据库中取出来的记录。
package cn.demo.entity;
public class Student {
private Integer id; //id
private String name; //学生名称
private String pwd; //登录密码
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", pwd=" + pwd + "]";
}
}
4.Student.hbm.xml
在实体类所在的路径下,创建一个实体类的Hibernate映射文件,用于告诉Hibernate框架Java对象与数据表中字段的映射关系。
<?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="cn.demo.entity.Student" table="student">
<id name="id" column="id" type="int">
<generator class="native" />
</id>
<property name="name"/>
<property name="pwd" />
</class>
</hibernate-mapping>
到此,Hibernate框架配置完毕。
5.HibernateUtils工具类
由上面介绍的Hibernate执行过程可知,Configuration和SessionFactory每次数据库操作时都会被实例化访问,因此我们把他们抽取出来,封装成为一个HibernateUtils的工具类,以便调用时不用每次都写那么多代码。
在src下新建cn.demo.utils包,在包中新建HibernateUtils类
package cn.demo.utils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtils {
private static final Configuration config;
private static final SessionFactory factory;
static {
config = new Configuration().configure();
factory = config.buildSessionFactory();
}
// 获取Session
public static Session getSession() {
return factory.openSession();
}
}
6.StudentTest类(测试类)
为了测试当前ORM是否生效,我们新建了一个cn.demo.test的包,用于存放对数据库操作的单元测试实例。并在包中新建一个测试类
package cn.demo.test;
import org.hibernate.Session;
import org.junit.Test;
import cn.demo.entity.Student;
import cn.demo.utils.HibernateUtils;
public class StudentTest {
@Test
public void test() {
// 1.得到session
Session session = HibernateUtils.getSession();
// 2.开启事务
session.beginTransaction();
// 3.操作
Student s1 = new Student();
s1.setName("eric");
s1.setPwd("pwd123");
session.save(s1);
// 4.提交事务
session.getTransaction().commit();
// 5.关闭资源
session.close();
}
}
其中,JUnit是一个进行单元测试的开源框架。@Test
表示用于测试的方法的注解。
若报出Test cannot be resolved to the build path提示,则需要把鼠标移动到 @Test
标签处,点击 Add JUnit4 library to the build path,程序会自动将JUnit4的支持包引入到本项目中。
只需点击执行的测试方法—右键—Run As—JUnit Test选项,即可运行单元测试。
改进
我们可以在现有基础上,把针对实体类的操作再进行封装。
cn.demo.entity包存放的是实体类,例如:User.java
cn.demo.operation包存放的是实体对应的操作,例如:UserOperation.java
package cn.demo.operation;
import org.hibernate.Session;
import cn.demo.utils.HibernateUtils;
import cn.demo.entity.User;
public class UserOperation {
//操作:插入一个用户操作
public static void InsertUser(User user){
Session session = HibernateUtils.getSession();
session.beginTransaction();
session.save(user);
session.getTransaction().commit();
session.close();
}
//查询一个用户……
//删除一个用户……
//更新一个用户……
//查询符合条件的用户集合……
}
作者: 肖sir@ZHBIT
2018 年 09月 27日
网友评论