一、 Hibernate概述
- Hibernate是什么?
根据三层架构,Hibernate主要是处理dao层,帮助完成数据库操作。是一个开放源代码ORM(对象关系映射)框架,对JDBC进行了轻量级的对象封装。运用面向对象的编程思想来操作数据库。 - 使用Hibernate的好处?
操作数据库的时候,可以以面向对象的方式来完成,不需要书写SQL语句。 - hibernate是一个orm框架
orm框架也就是对象关系映射。orm分为4级,hibernate属于4级,完全面向对象操作数据库。mybatis属于2级,dbutils属于1级。
二、 Hibernate框架搭建(快速入门)
第一步:下载最新的hibernate的包
我们首先在hibernate官网中下载最新的hibernate的包
随后
第二步:导包并进行查看
- documentation文件夹:存在Hibernate相关文档,包括参考文档的API文档
- lib文件夹:存放Hibernate编译和运行所依赖的jar包。其中required子目录下的包运行了Hibernate5项目必须的JAR包。
- project文件夹:存放Hibernate各种相关的源代码。
此处我们导包需要导入lib下面的required中的jar包
以及数据库连接包
第三步:创建数据库以及表
附上脚本
CREATE TABLE `cst_customer` (
`cust_id` BIGINT(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)',
`cust_name` VARCHAR(32) NOT NULL COMMENT '客户名称(公司名称)',
`cust_source` VARCHAR(32) DEFAULT NULL COMMENT '客户信息来源',
`cust_industry` VARCHAR(32) DEFAULT NULL COMMENT '客户所属行业',
`cust_level` VARCHAR(32) DEFAULT NULL COMMENT '客户级别',
`cust_linkman` VARCHAR(64) DEFAULT NULL COMMENT '联系人',
`cust_phone` VARCHAR(64) DEFAULT NULL COMMENT '固定电话',
`cust_mobile` VARCHAR(16) DEFAULT NULL COMMENT '移动电话',
PRIMARY KEY (`cust_id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
第四步:创建实体类
public class Customer {
private Long cust_id;
private String cust_name;
private String cust_source;
private String cust_industry;
private String cust_level;
private String cust_linkman;
private String cust_phone;
private String cust_mobile;
//此处省略了getter/setter方法,真正代码中需要添加
}
第五步:配置映射对象与表的配置文件(orm元数据)
实体Customer目前不具备持久化操作的能力,而hibernate需要知道实体类Customer隐射到数据库Hibernate中的哪个表,以及类中的哪个属性对应数据库表中的哪个字段。
在实体类Customer所在的包中,创建一个名称为Customer.hbm.xml的映射文件,该文件中定义了实体类的属性是如何映射到数据库表中的列名的
在我们创建映射文件,我们需要引入约束。在项目导入的jar包中找到
引入约束
往下翻,会看到 dtd配置文件
其次,引入这段代码到项目中,及引入了约束(DTD约束)
<?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">
<!-- 配置表与实体对象的关系 -->
<!-- package属性:填写一个报名,在元素内部凡是需要书写完整类名的属性,可以直接写类名 -->
<hibernate-mapping package="com.aiit.domain">
<!--
class元素:配置实体与表的对应关系的
name:完整类名
table:数据库表名
-->
<class name="Customer" table="cst_customer">
<!-- id元素:配置主键映射的属性
name:填写主键对应属性名
colunm(可选):填写表中的主键的列名,默认值:列名会默认使用属性名
type(可选):填写列(属性)的类型。如果不写hibernate会自动检测属性类型,
但是如果手写可以有三种语法java类型|hibernate类型|数据库类型
not-null(可选):配置该属性(列)是否不能为空,默认值为:false
length(可选)::配置数据库中列的长度,默认值:使用数据库类型的最大长度。如:varchar(255位),int(9位)
-->
<id name="cust_id" column="cust_id">
<generator class="native"></generator>
</id>
<!-- property除di之外的普通属性映射
name:填写主键对应属性名
colunm:填写表中的列名
type(可选):填写列(属性)的类型。如果不写hibernate会自动检测属性类型,
但是如果手写可以有三种语法java类型|hibernate类型|数据库类型
not-null(可选):配置该属性(列)是否不能为空,默认值为:false
length(可选)::配置数据库中列的长度,默认值:使用数据库类型的最大长度。如:varchar(255位),int(9位)
-->
<property name="cust_name" column="cust_name" type=""></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_linkman" column="cust_linkman"></property>
<property name="cust_phone" column="cust_phone"></property>
<property name="cust_mobile" column="cust_mobile"></property>
</class>
</hibernate-mapping>
第六步:配置核心文件
其反映了dao层和数据库表的映射信息,而hibernate的配置文件主要用来配置数据库连接以hibernate
运行所需要的各个属性的值。在项目的src下创建一个名称为hibernate.cfg.xml
文件我们在配置文件是以键值对的形式出现,键主要是以key为主。我们可以找到hibernate目录下的project
——>etc
——>hibernate.properties文件
,里面包含了所有的键。我们只需要从中获取相应的键即可。
例如:
如我们需要连接数据库,只需要搜索mysql。找到key值即可
主配置文件
<?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>
<!--
#hibernate.dialect org.hibernate.dialect.MySQLDialect
#hibernate.dialect org.hibernate.dialect.MySQLInnoDBDialect
#hibernate.dialect org.hibernate.dialect.MySQLMyISAMDialect
#hibernate.connection.driver_class com.mysql.jdbc.Driver
#hibernate.connection.url jdbc:mysql:///test
#hibernate.connection.username gavin
#hibernate.connection.password
-->
<!-- 数据库驱动 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- 数据库url -->
<property name="hibernate.connection.url">jdbc:mysql:///hibernate_day01</property>
<!-- 数据库连接用户名 -->
<property name="hibernate.connection.username">root</property>
<!-- 数据库连接密码 -->
<property name="hibernate.connection.password">123</property>
<!-- 数据库方言
不同的数据库中,sql语法略有区别. 指定方言可以让hibernate框架在生成sql语句时.针对数据库的方言生成.
sql99标准: DDL 定义语言 库表的增删改查
DCL 控制语言 事务 权限
DML 操纵语言 增删改查
注意: MYSQL在选择方言时,请选择最短的方言.
-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- #hibernate.show_sql true
#hibernate.format_sql true
-->
<!-- 将hibernate生成的sql语句打印到控制台 -->
<property name="hibernate.show_sql">true</property>
<!-- 将hibernate生成的sql语句格式化(语法缩进) -->
<property name="hibernate.format_sql">true</property>
<!--
## auto schema export 自动导出表结构. 自动建表
#hibernate.hbm2ddl.auto create 自动建表.每次框架运行都会创建新的表.以前表将会被覆盖,表数据会丢失.(开发环境中测试使用)
#hibernate.hbm2ddl.auto create-drop 自动建表.每次框架运行结束都会将所有表删除.(开发环境中测试使用)
#hibernate.hbm2ddl.auto update(推荐使用) 自动生成表.如果已经存在不会再生成.如果表有变动.自动更新表(不会删除任何数据).
#hibernate.hbm2ddl.auto validate 校验.不自动生成表.每次启动会校验数据库中表是否正确.校验失败.
-->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 引入orm元数据
路径书写: 填写src下的路径
-->
<mapping resource="/com/aiit/domain/Customer.hbm.xml" />
</session-factory>
</hibernate-configuration>
第七步:书写测试类
public class Demo {
@Test
//保存客户
public void fun1() {
Configuration configuration =new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
//--------------------------------------------------
Customer customer =new Customer();
customer.setCust_name("aiit");
session.save(customer);//执行保存
//--------------------------------------------------
tx.commit();
session.close();
sessionFactory.close();
}
}
此时我们的控制台可以打印出sql语句以及数据库会同步增加数据
三、详解配置文件
1.orm元数据
我们对对应的上面第一个xml文件进行解析
-
<hibernate-mapping package="com.aiit.domain">
书写package,package属性:填写一个报名,在元素内部凡是需要书写完整类名的属性,可以直接写类名 -
class元素
:配置实体与表的对应关系的- name:完整类名
- table:数据库表名
-
id元素
:配置主键映射的属性- name:填写主键对应属性名
- colunm(可选):填写表中的主键的列名,默认值:列名会默认使用属性名
- type(可选):填写列(属性)的类型。如果不写hibernate会自动检测属性类型,
但是如果手写可以有三种语法java类型|hibernate类型|数据库类型 - not-null(可选):配置该属性(列)是否不能为空,默认值为:false
- length(可选):配置数据库中列的长度,默认值:使用数据库类型的最大长度。如:varchar(255位),int(9位)
-
propert元素
除id以外的所有元素- name:填写主键对应属性名
- colunm:填写表中的列名
- type(可选):填写列(属性)的类型。如果不写hibernate会自动检测属性类型,
但是如果手写可以有三种语法java类型|hibernate类型|数据库类型 - not-null(可选):配置该属性(列)是否不能为空,默认值为:false
- length(可选):配置数据库中列的长度,默认值:使用数据库类型的最大长度。如:varchar(255位),int(9位)
2.主配置文件
- 必选元素
<!-- 数据库驱动 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- 数据库url -->
<property name="hibernate.connection.url">jdbc:mysql:///hibernate_day01</property>
<!-- 数据库连接用户名 -->
<property name="hibernate.connection.username">root</property>
<!-- 数据库连接密码 -->
<property name="hibernate.connection.password">123</property>
<!-- 数据库方言
不同的数据库中,sql语法略有区别. 指定方言可以让hibernate框架在生成sql语句时.针对数据库的方言生成.
sql99标准: DDL 定义语言 库表的增删改查
DCL 控制语言 事务 权限
DML 操纵语言 增删改查
注意: MYSQL在选择方言时,请选择最短的方言.
-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
- 格式化输出语句(两个属性常结合一起)
<!-- #hibernate.show_sql true
#hibernate.format_sql true-->
<!-- 将hibernate生成的sql语句打印到控制台 -->
<property name="hibernate.show_sql">true</property>
<!-- 将hibernate生成的sql语句格式化(语法缩进) -->
<property name="hibernate.format_sql">true</property>
- 可选属性
其有四种方式hibernate.hbm2ddl.auto (create)
:自动建表.每次框架运行都会创建新的表.以前表将会被覆盖,表数据会丢失.(开发环境中测试使用)hibernate.hbm2ddl.auto (create-drop)
:自动建表.每次框架运行结束都会将所有表删除.(开发环境中测试使用)hibernate.hbm2ddl.auto (update(推荐使用))
:自动生成表.如果已经存在不会再生成.如果表有变动.自动更新表(不会删除任何数据).hibernate.hbm2ddl.auto (validate)
:校验.不自动生成表.每次启动会校验数据库中表是否正确.校验失败.
<!--
## auto schema export 自动导出表结构. 自动建表
#hibernate.hbm2ddl.auto (create) 自动建表.每次框架运行都会创建新的表.以前表将会被覆盖,表数据会丢失.(开发环境中测试使用)
#hibernate.hbm2ddl.auto (create-drop) 自动建表.每次框架运行结束都会将所有表删除.(开发环境中测试使用)
#hibernate.hbm2ddl.auto (update(推荐使用)) 自动生成表.如果已经存在不会再生成.如果表有变动.自动更新表(不会删除任何数据).
#hibernate.hbm2ddl.auto (validate) 校验.不自动生成表.每次启动会校验数据库中表是否正确.校验失败.
-->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 引入orm元数据
路径书写: 填写src下的路径
-->
<mapping resource="/com/aiit/domain/Customer.hbm.xml" />
- 引入orm元数据
<mapping resource="/com/aiit/domain/Customer.hbm.xml" />
四、Hibernate中的API
1. Configuration:配置对象
Configuration主要用于Hibernate框架加载映射文件
在使用hibernate是首先要创建Configuation实例,Configuration实例主要用于启动、加载、管理hibernate的配置文件信息。在启动hibernate的过程中,Configuration实例首先确定hibernate配置文件的位置,然后读取相关配置,最后创建一个唯一的SessionFactory实例。
通常使用Configuration configuration =new Configuration()
的方式创建实例。
此种方法会默认去src下读取hibernate.cfg.xml配置文件,如果不想使用默认的hibernate.cfg.xml
配置文件,而是使用指定目录的配置文件,需要往confige()方法中传递一个文件路径参数如下:
Configuration configuration =new Configuration().configure(“xml文件位置”)
//1,创建,调用空参构造
Configuration configuration =new Configuration();
//2.读取指定配置文件,空参加载方法,加载src下的hibernate.cfg.xml文件
configuration.configure();
//3.读取指定orm元数据()
//configuration.addResource(resourceName);
//configuration.addClass(persistentClass)
//根据配置信息,创建SessionFactory对象
SessionFactory buildSessionFactory = configuration.buildSessionFactory();
2. SessionFactory : Session工厂对象
SessionFactory接口负责Hibernate的初始化和建立Session对象,它在hibernate中起到一个缓冲区的作用,Hibernate可以讲自动生成的SQL语句,映射数据以及某些可重复利用的数据放在这个缓冲区中。同时他还保存了对数据库配置的所有映射关系,维护了当前的二级缓存。
SessionFactory实例是通过Configuration对象获取的,其获取方法如下:
SessionFactory buildSessionFactory = configuration.buildSessionFactory()
特点:
-
它是线程安全的,同一个实例能够贡多个线程共享。
-
它是轻量级的,不能随意的创建和销毁它的实例。
//根据配置信息,创建SessionFactory对象
SessionFactory sf = configuration.buildSessionFactory();
//5.获得session
//打开一个新的session对象
sf.openSession();
//获得一个与线程绑定的session对象()
sf.getCurrentSession();
由于SesssionFactory的这些特点,一般情况下,一个项目中只需要一个SesssionFactory,只有当应用中存在多个数据源时,才为每个数据建立一个SessionFactory实例,在实际项目中,通常会抽取一个Hibernate的工具类,用来提供Session对象.
书写HibernateUtils工具类
public class HibernateUtils {
private static final SessionFactory sf;
private static final Configuration conf;
static {
//1.创建,调用空参构造
conf =new Configuration().configure();
//2.根据配置信息,创建SessionFactory对象
sf = conf.buildSessionFactory();
}
public static Session openSession() {
//3.获得Session
Session session = sf.openSession();
return session;
}
public static Session getCurrentSession() {
//3.获得Session
Session session = sf.getCurrentSession();
return session;
}
}
3. Session
Session接口负责执行被持久化对象的CRUD(增删改查)操作的任务与完成数据库的交流,它是应用程序与数据库之间交互操作的一个单线程对象,是Hibernate运作的中心。
注意Session对象是线程不安全的
我们在创建SessionFactory实例后,就可以通过它获取Session实例。
获取Session实例有两种方式,
一种是openSession()
方法,另外一种是通过getCurrentSession()
方法
//根据配置信息,创建SessionFactory对象
SessionFactory sf = configuration.buildSessionFactory();
//5.获得session
//打开一个新的session对象
sf.openSession();
//获得一个与线程绑定的session对象()
sf.getCurrentSession();
以上两种获取session实例方式主要区别是,采用第一种方法获取Session实例时,SessionFactory直接创建一个新的Session实例,并且在使用完成后需要手动调用close方法进行关闭,而getCurrentSession方法会创建Session实例会被绑定到当前线程中,它在提交或回滚操作会进行自动关闭。
在Session中提供了大量的常用方法:
- save(),update()和saveOrUpdate()方法:用于增加和修改对象
- delete()方法:用于删除对象
- get()和load()方法:根据主键查询
- createQuery()和createSQLQuery()方法:用于数据库操作对象
- createCriteria()方法:条件查询
//1.创建,调用空参构造函数
Configuration configuration = new Configuration().configure();
//2.根据配置信息,创建SessionFactory对象
SessionFactory sf = configuration.buildSessionFactory();
//3.获得Session
Session session = sf.openSession();
//4.开启事务并获得操作事务的tx对象
Transaction beginTransaction = session.beginTransaction();
//添加一条数据 -------------------
Customer customer =new Customer();
customer.setCust_name("王五");
session.save(customer);
Session的get方法,根据id查
//此时的id是long类型,加l表示long型
Customer customer = session.get(Customer.class, 1l);
System.out.println(customer);
修改id为1对象的name属性
//第一步获得需要修改的对象
Customer customer = session.get(Customer.class, 1l);
///第二步:进行修改
customer.setCust_name("李四");
session.update(customer);
删除id为1的对象
//第一步获得需要修改的对象
Customer customer = session.get(Customer.class, 3l);
//调用delet方法
session.delete(customer);
beginTransaction.commit();
session.close();
sf.close();
4. Transaction
Transaction接口主要用于管理事务,是Hibernate的数据库事务接口,且对底层的事务接口进行了封装。Transaction接口的事务对象是通过Session对象开启的。
//获得操作事务的tx对象
Transaction transaction = session.getTransaction();
//开启事务并获得操作事务的tx对象(开发中使用)
Transaction beginTransaction = session.beginTransaction();
在Transaction接口中,提供了事务管理的常用方法,
- commit()方法:提交相关联的session实例
- rollback()方法:撤销事务操作。
Session执行完数据库操作后,要使用Transaction接口的commit()方法进行事务提交,才能真正的将数据操作同步到数据库中。发生异常的时候,需要使用rollback()方法进行事务回滚,以避免数据发生错误。因此持久化操作后,必须调用Transaction接口的commit()方法和rollback()方法。如果没有开启事务,那么每个Session的操作,都相当于一个独立的操作。
上面两种方法若使用方法一,需要手动开启事务。