1. hibernate框架
框架的含义:
- 1.框架是用来提高开发效率的
- 2.封装了好了一些功能.我们需要使用这些功能时,调用即可.不需要再手动实现.
- 3.所以框架可以理解成是一个半成品的项目.只要懂得如何驾驭这些功能即可.
javaEE三层开发框架及hibernate框架对应的位置如下:
Hibernate框架优点: 操作数据库的时候,可以以面向对象的方式来完成.不需要书写SQL语句
Hibernate框架:是当今主流的Java持久层框架之一,由于它具有简单易学、灵活性强、扩展性强等特点,能够大大地简化程序的代码量,提高工作效率,因此受到广大开发人员的喜爱。
Hibernate是一个开放源代码的ORM(object relationship mapping,关系对象映射)框架,它对JDBC进行了轻量级的对象封装,使得Java开发人员可以使用面向对象的编程思想来操作数据库。
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。
为什么学习Hibernate?
使用传统的JDBC开发应用系统时,如果是小型应用系统,并不觉得有什么麻烦,但是由于大型应用系统的开发,使用JDBC就会显得力不从心。例如对几十、几百张包含几十个字段的表进行插入操作时,编写的SQL语句不但很长,而且繁琐,容易出错;在读取数据时,需要写多条getXxx语句从结果集中取出各个字段的信息,不但枯燥重复,并且工作量非常大。为了提高数据访问层的编程效率,Gravin King开发出了一个当今最流行的ORM框架,它就是Hibernate框架。
所谓的ORM就是利用描述对象和数据库表之间映射的元数据,自动把Java应用程序中的对象,持久化到关系型数据库的表中(自动创建表)。通过操作Java对象,就可以完成对数据库表的操作。可以把ORM理解为关系型数据和对象的一个纽带,开发人员只需要关注纽带一端映射的对象即可。ORM原理:
与其它操作数据库的技术相比,Hibernate具有以下优势:
- Hibernate对JDBC访问数据库的代码做了轻量级封装,大大简化了数据访问层繁琐的重复性代码,并且减少了内存消耗,加快了运行效率。
- Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现,它很大程度的简化了DAO(Data Access Object,数据访问对象)层编码工作。
- Hibernate的性能非常好,映射的灵活性很出色。它支持很多关系型数据库,从1对1到多对多的各种复杂关系。
- 可扩展性强,由于源代码的开源以及API的开放,当本身功能不够用时,可以自行编码进行扩展。
orm分4级
hibernate属于4级:完全面向对象操作数据库
mybatis属于2级
dbutils属于1级
Hibernate5.0.7的目录介绍:
- documentation文件夹:存放Hibernate的相关文档,包括参考文档的API文档。
- lib文件夹:存放Hibernate编译和运行所依赖的JAR包。其中required子目录下包含了运行Hibernate5项目必须的JAR包。
- project文件夹:存放Hibernate各种相关的源代码。
2. Hibernate入门
框架搭建
- 导包
lib/required子目录中,包含的JAR包
驱动包
日志记录包
- 创建实体(持久化类):创建数据库,准备表,实体
持久化类是应用程序中的业务实体类,这里的持久化是指类的对象能够被持久化保存到数据库中。
Hibernate使用普通Java对象(Plain Old Java Object),即POJO的编程模式来进行持久化。POJO类中包含的是与数据库表相对应的各个属性,这些属性通过getter和setter方法来访问,对外部隐藏了内部的实现细节。下面就来编写Customer持久化类。
在项目src目录下,创建cn.eagle.domain包,并在保重创建类Customer(对应数据库表cst_customer),Customer类包含了与cst_customer数据表字段对应的属性,以及相应的getXxx()和setXxx()方法。

1 package cn.eagle.domain; 2 3 public class Customer { 4 5 private Long cust_id; 6 private String cust_name; 7 private String cust_source; 8 private String cust_industry; 9 private String cust_level; 10 private String cust_phone; 11 private String cust_mobile; 12 13 public Long getCust_id() { 14 return cust_id; 15 } 16 17 public void setCust_id(Long cust_id) { 18 this.cust_id = cust_id; 19 } 20 21 public String getCust_name() { 22 return cust_name; 23 } 24 25 public void setCust_name(String cust_name) { 26 this.cust_name = cust_name; 27 } 28 29 public String getCust_source() { 30 return cust_source; 31 } 32 33 public void setCust_source(String cust_source) { 34 this.cust_source = cust_source; 35 } 36 37 public String getCust_industry() { 38 return cust_industry; 39 } 40 41 public void setCust_industry(String cust_industry) { 42 this.cust_industry = cust_industry; 43 } 44 45 public String getCust_level() { 46 return cust_level; 47 } 48 49 public void setCust_level(String cust_level) { 50 this.cust_level = cust_level; 51 } 52 53 public String getCust_phone() { 54 return cust_phone; 55 } 56 57 public void setCust_phone(String cust_phone) { 58 this.cust_phone = cust_phone; 59 } 60 61 public String getCust_mobile() { 62 return cust_mobile; 63 } 64 65 public void setCust_mobile(String cust_mobile) { 66 this.cust_mobile = cust_mobile; 67 } 68 69 @Override 70 public String toString() { 71 return "Customer [cust_id=" + cust_id + ", cust_name=" + cust_name + ", cust_source=" + cust_source 72 + ", cust_industry=" + cust_industry + ", cust_level=" + cust_level + ", cust_phone=" + cust_phone 73 + ", cust_mobile=" + cust_mobile + "]"; 74 } 75 76 }
- 创建映射文件
实体类Customer目前还不具备持久化操作的能力,而Hibernate需要知道实体类Customer映射到数据库Hibernate中的哪个表,以及类中的哪个属性对应数据库表中的哪个字段,这些都需要在映射文件中配置。
在实体类Customer所在的包中,创建一个名称为Customer.hbm.xml的映射文件,在该文件中定义了实体类Customer的属性是如何映射到cst_customer表的列上的。

1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 3 <hibernate-mapping> 4 <class name="cn.eagle.domain.Customer" table="cst_customer"> 5 <id name="cust_id" column="cust_id"> 6 <generator class="native"></generator> 7 </id> 8 <property name="cust_name" column="cust_name"></property> 9 <property name="cust_source" column="cust_source"></property> 10 <property name="cust_industry" column="cust_industry"></property> 11 <property name="cust_level" column="cust_level"></property> 12 <property name="cust_phone" column="cust_phone"></property> 13 <property name="cust_mobile" column="cust_mobile"></property> 14 </class> 15 </hibernate-mapping>
- 创建Hibernate的核心配置文件
Hibernate的映射文件反映了持久化类和数据库表的映射信息,而Hibernate的配置文件则主要用来配置数据库连接以及Hibernate运行时所需要的各个属性的值。在项目的src下创建一个名称为hibernate.cfg.xml的文件

1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd" > 3 <hibernate-configuration> 4 <session-factory> 5 <property name="hibernate.connection.dirver_class">com.mysql.jdbc.Driver</property> 6 <property name="hibernate.connection.url">jdbc:mysql:///day24_db</property> 7 <property name="hibernate.connection.username">root</property> 8 <property name="hibernate.connection.password">toor</property> 9 <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> 10 <property name="hibernate.show_sql">true</property> 11 <property name="hibernate.format_sql">true</property> 12 <property name="hibernate.hbm2ddl.auto">update</property> 13 <mapping resource="cn/eagle/domain/Customer.hbm.xml"/> 14 </session-factory> 15 </hibernate-configuration>
3. Hibernate配置文件详解
在以上部分中,我们已经接触过Hibernate的映射文件和配置文件。接下来,将对这些文件进行详细的讲解。
- 映射文件Customer.hbm.xml用于向Hibernate提供持久化类到关系型数据库的映射,每个映射文件的结构基本都是相同的,其普遍的代码形式如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<!-- 映射文件的dtd信息 -->
<!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:完整类名;
table:数据库表名。(如果类名和表名是一致的,那么table属性可以省略) -->
<class name="cn.eagle.domain.Customer" table="cst_customer">
<!-- id元素:配置主键映射的属性
name:主键对应的属性名;
column(可选):填写表中的主键列名。默认值:列名会默认使用属性名;
type(可选):填写列(属性)的类型。Hibernate会自动检测实体的属性类型。
每个类型有三种填法:java类型|hibernate类型(默认)|数据库类型;
not-null(可选):配置该属性(列)是否不能为空。默认值:false
length(可选):配置数据库中列的长度,默认值:使用数据库类型的最大长度
-->
<id name="cust_id" column="cust_id">
<generator class="native"></generator> // 主键的生成策略
</id>
<!-- 其它属性使用property标签来映射 -->
<property name="cust_name" column="cust_name"></property>
<property name="cust_source" column="cust_source"></property>
<property name="cust_industry" column="cust_industry"></property>
<property name="cust_level" column="cust_level"></property>
<property name="cust_phone" column="cust_phone"></property>
<property name="cust_mobile" column="cust_mobile"></property>
</class>
</hibernate-mapping>
映射文件通常是一个xml文件即可,但一般命名为类名.hbm.xml
- 核心配置文件hibernate.cfg.xml包含了连接持久层与映射文件所需的基本信息,其配置文件有两种格式,具体如下:
- 一种是properties属性文件格式的配置文件,它使用键值对的形式存放信息,默认文件名称为Hibernate.properties;
- 另一种是XML格式的配置文件,XML配置文件的默认名称为hibernate.cfg.xml。
上述两种配置文件是等价的,具体使用哪个可以自由选择。XML格式的配置文件更易于修改,配置能力更强,当改变低层应用配置时不需要改变和重新编译代码,只修改配置文件的相应属性即可,而properties格式的文件则不具有次优势,因此,在实际开发项目中,大多数情况会使用XML格式的配置文件。下面将对XML格式的配置文件进行详细介绍。
hibernate.cfg.xml配置文件一般在开发时会放置在src的源文件夹下,发布后,该文件会在项目的WEB-INF/classes路径下。配置文件的常用配置信息如下所示。
<?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>
<!-- 5个必选连接数据库基本参数属性
hibernate.connection.dirver_class 数据库驱动
hibernate.connection.url 数据库url
hibernate.connection.username 数据库连接用户名
hibernate.connection.password 数据库连接密码
hibernate.dialect 数据库方言,不同的数据库中,sql语法略有区别,
指定方言可以让hibernate框架在生成sql语句时,针对数据库的方言生成;
sql99标准:DDL 定义语言 库表的增删改查
DCL 控制语言 事务、权限
DML 操纵语言 增删改查
注意: Mysql在选择方言时,请选择最短的方言
hibernate.connection.autocommit 可选,事务是否自动提交
-->
<property name="hibernate.connection.dirver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///day24_db</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">toor</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 3个可选属性
hibernate.show_sql 将hibernate生成的sql语句打印到控制台
hibernate.format_sql 将hibernate生成的sql语句格式化(语法缩进)
hibernate.hbm2ddl.auto (auto scheme export 自动导出表结构,自动建表)
create: 自动建表.每次框架运行都会创建新的表,以前的表将会被覆盖,表数据会丢失。(开发环境中测试使用)
create-drop: 自动建表。每次框架运行结束都会将所有表删除。(开发环境中测试使用)
update: 推荐使用 自动生成表,如果已经存在不会再生成,如果表有变动,自动更新表(不会删除任何数据)
validate: 校验 不自动生成表。每次启动会校验数据库中表是否正确,只会使用原有的表 -->
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 引入orm源数据
路径书写:填写src下的路径 -->
<mapping resource="cn/eagle/domain/Customer.hbm.xml" />
</session-factory>
</hibernate-configuration>
4. Hibernate API详解
- Configuration
Configuration主要用于Hibernate框架加载映射文件,它的作用是对Hibernate进行配置,以及对它进行启动。在Hibernate的启动过程中,Configuration类的实例首先定位映射文档的位置,读取这些配置,然后创建一个SessionFactory对象。虽然Configuration类在整个Hibernate项目中只扮演着一个很小的角色,但他是启动hibernate时所遇到的第一个对象;
Configuration实例用于启动、加载、管理hibernate的配置文件信息。在启动Hibernate的过程中,Configuration实例首先确定Hibernate配置文件的位置,然后读取相关配置,最后创建一个唯一的SessionFactory实例。Configuration对象只存在于系统的初始化阶段,它将SessionFactory创建完成后,就完成了自己的使命。
Configuration cfg = new Configuration().configure();
此种方式默认会去src下读取hibernate.cfg.xml配置文件。如果不想使用默认的hibernate.cfg.xml配置文件,而是使用指定目录下(或自定义)的配置文件,则需要向configuration()方法中传递一个文件路径的参数即可。
也可以使用该对象加载映射文件:
configuration.addResource("cn/eagle/domain/Customer.hbm.xml");
- SessionFactory
该接口负责初始化Hibernate。它充当数据存储源的代理,并负责创建Session对象。这里用到了工厂模式。需要注意的是SessionFactory并不是轻量级的,因为一般情况下,一个项目通常只需要一个SessionFactory就够,当需要操作多个数据库时,可以为每个数据库指定一个SessionFactory。
SessionFactory接口负责Hibernate的初始化和建立Session对象。它在Hibernate中起到一个缓冲区作用,Hibernate可以将自动生成的SQL语句、映射数据以及某些可重复利用的数据放在这个缓冲区中。同时它还保存了对数据库配置的所有映射关系,维护了当前的二级缓存。
SessionFactory实例是通过Configuration对象获取的,其获取方法如下所示:
SessionFactory sessionFactory = cfg.buildSessionFactory();
它的特点如下:
1. 它是线程安全的,它的同一个实例能够供多个线程共享。
2. 它是重量级的,不能随意的创建和销毁它的实例
3. 负责保存和使用所有配置信息,消耗内存资源非常大
4. 保证在web项目中,值创建一个SessionFactory
由于SessionFactory的这些特点,一般情况下,一个项目中只需要一个SessionFactory,只有当应用中存在多个数据源时,才为每个数据源建立一个SessionFactory实例。因此,在实际项目使用中,通常会抽取出一个HibernateUtils的工具类,用来提供Session对象。
SessionFactory内部还维护了一个连接池,如果我们需要使用第三方的连接池如C3P0,那么需要我们自己手动进行配置
<!-- 配置C3P0连接池 -->
<property name="connection.provider_class">org.hibernate.c3p0.internal.C3P0ConnectionProvider</property>
<!-- 在连接池中可用的数据库连接的最少数目 -->
<property name="c3p0.min_size">5</property>
<!-- 在连接池中所有数据库连接的最大数目 -->
<property name="c3p0.max_size">20</property>
<!-- 设定数据库连接的过期时间,以秒为单位,如果连接池中的某个数据库连接处于
空闲状态的时间超过了timeout时间,就会从连接池中清除 -->
<property name="c3p0.timeout"></property>
<!-- 每3000秒检查所有连接池中的空闲连接,以秒为单位 -->
<property name="c3p0.idle_test_period">3000</property>
测试C3P0连接池
新建测试单元

1 package cn.eagle.test; 2 3 import static org.junit.Assert.*; 4 5 import java.sql.Connection; 6 import java.sql.SQLException; 7 8 import org.hibernate.Session; 9 import org.hibernate.SessionFactory; 10 import org.hibernate.Transaction; 11 import org.hibernate.cfg.Configuration; 12 import org.hibernate.jdbc.Work; 13 import org.junit.After; 14 import org.junit.Before; 15 import org.junit.Test; 16 17 public class HibernateTestC3P0 { 18 private SessionFactory sessionFactory; 19 private Session session; 20 private Transaction transaction; 21 22 @Before 23 public void init() { 24 Configuration configuration = new Configuration().configure(); 25 sessionFactory = configuration.buildSessionFactory(); 26 session = sessionFactory.openSession(); 27 transaction = session.beginTransaction(); 28 } 29 30 @After 31 public void destroy() { 32 transaction.commit(); 33 session.close(); 34 sessionFactory.close(); 35 } 36 37 @Test 38 public void test() { 39 session.doWork(new Work() { 40 41 @Override 42 public void execute(Connection conn) throws SQLException { 43 System.out.println(conn); 44 } 45 46 }); 47 } 48 49 }
- Session
Session接口负责执行被持久化对象的CRUD操作(CRUD的任务是完成与数据库的交流,包含了很多常见的SQL语句)。但需要注意的是Session对象是非线程安全的。同时,Hibernate不同于JSP应用中的HttpSession。这里当使用session这个术语时,其实指的是Hibernate中的session,而以后会将HttpSession对象称为用户session。
Session是应用程序与数据库之间交互操作的一个单线程对象,是Hibernate运作的中心,它的主要功能是为持久化对象提供创建、读取和删除的能力,所有持久化对象必须在session的管理下才可以进行持久化操作。
创建SessionFactory实例后,就可以通过它获取Session实例。获取Session实例有两种方式,
一种是通过openSession()方法,另外一种是通过getCurrentSession()方法。两种方法获取session的代码如下所示:
Session session = sessionFactory.openSession();
Session session = sessionFactory.getCurrentSession();
以上两种获取session实例方式的主要区别是,采用openSession方法获取Session实例时,SessionFactory直接创建一个新的Session实例,并且在使用完成后需要调用close方法进行手动关闭。而getCurrentSession方法创建的Session实例会被绑定到当前线程中,它在提交或回滚操作时会自动关闭。
Session是线程不安全的,多个并发线程同时操作一个Session实例时,就可能导致Session数据存取的混乱(方法内部定义和使用Session时,不会出现线程问题)。因此设计软件架构时,应避免多个线程共享一个Session实例。同时,它也是轻量级的,实例的创建和销毁不需要消耗太多的资源。它还有给个缓存,即Hibernate的一级缓存,这个缓存主要用于存放当前工作单元加载的对象。
在Session中提供了大量的常用方法,具体如下:
1. save()、update()和saveOrUpdate()方法:用于增加和修改对象。
2. delete()方法:用于删除对象。
3. get()和load()方法:根据主键查询。
4. createQuery()和createSQLQuery()方法:用于数据库操作对象。
5. createCriteria()方法:条件查询。
- Transaction
Transaction接口是一个可选的API,可以选择不适用这个接口,取而代之的是Hibernate的设计者自己写的底层事务处理代码。Transaction接口是对实际事务实现的一个抽象,这些实现包括JDBC事务、JTA中的UserTransaction、甚至可以是CORBA事务。之所以这样设计是能让开发者能够使用一个统一事务的操作界面,使得自己的项目可以在不同的环境和容器之间方便地移植。
Transaction接口主要用于管理事务,它是Hibernate的数据库事务接口,且对底层的事务接口进行了封装。Transaction接口的事务对象是通过Session对象开启的,其开启方式如下所示。
Transaction tx = session.beginTransaction();
在Transaction接口中,提供了事务管理的常用方法,具体如下:
1. commit()方法:提交相关联的session实例。
2. rollback()方法: 撤销事务操作。
Session执行完数据库操作后,要使用Transaction接口的commit()方法进行事务提交,才能真正的将数据库操作同步到数据库中。发生异常时,需要使用rollback()方法进行事务回滚,以避免数据发生错误。因此,在持久化操作后,必须调用Transaction接口的commit()方法和rollback()方法。如果没有开启事务,那么每个Session操作,都相当于一个独立的操作。