Hibernate第一天
1.为什么要学习Hibernate
1.1.基于JavaEE规范的三层架构
展现层(WEB层):处理请求与响应
业务层:处理业务逻辑
持久层:与数据库交互
1.2.持久层和Hibernate在Java应用程序中的角色
Hibernate的优势:
屏蔽了应用程序与数据库之间的联系,让应用程序操作数据库更加简单。
当底层数据库变换后,应用程序不需要改变,方便。
2.Hibernate框架的概述
2.1.Hibernate概述
Hibernate就是一个持久层的ORM框架。对JDBC做了轻量级的封装。
2.2.什么是框架
框架是可以重复使用的一些或一整套代码,通常与具体业务无关,也可以认为是软件的半成品。
使用框架的好处:简化项目的开发,提高开发效率。
2.3.什么是ORM
ORM:Object Relational Mapping,对象关系映射。
- O:面向对象领域的Object(JavaBean对象)
- R:关系数据库领域的Relational(表的结构)
- M:映射Mapping(XML的配置文件)
简单一句话:Hibernate使程序员通过操作对象的方式来操作数据库表记录。
2.4.Hibernate的优势
传统的JDBC和Hibernate开发对比图
3.Hibernate的快速入门
3.1.下载Hibernate5的运行环境
官网地址:http://hibernate.org/orm/
官网上最新的版本是5.2.10,本课程使用5.0.7
官方发布包目录结构如下:
documentation:存放官方的API文档和使用文档
lib:存放jar包
project:存放源码
3.2.搭建Hibernate5开发环境
创建Java工程:hibernate5_day01
引入hibernate5开发所需的jar包
在hibernate5_day01下新建lib文件夹
复制官方发布lib包中required下的jar包到工程lib目录下
全选lib下所有的jar包,右键,build path
注意:不要忘记了,还要引入数据库驱动的jar包,因为hibernate要操作数据库,只要是操作数据库,这个包就不能少。
完整jar包如下所示:
3.3.创建表结构
新建数据库:hibernate,注意编码格式为UTF-8
创建表:cst_customer,建表语句如下:
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_address
varchar(128) DEFAULT NULL COMMENT ‘客户联系地址’,
cust_phone
varchar(64) DEFAULT NULL COMMENT ‘客户联系电话’,
PRIMARY KEY (cust_id
)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
3.4.编写JavaBean实体类
新建实体类包:cn.itcast.domain,在包中新建实体类:
/**
-
客户实体类
-
@author kevin
*/
public class Customer implements Serializable{private static final long serialVersionUID = 1L;
private Long cust_id;
private String cust_name;
private String cust_source;
private String cust_industry;
private String cust_level;
private String cust_address;
private String cust_phone;
public Long getCust_id() {
return cust_id;
}
public void setCust_id(Long cust_id) {
this.cust_id = cust_id;
}
public String getCust_name() {
return cust_name;
}
public void setCust_name(String cust_name) {
this.cust_name = cust_name;
}
public String getCust_source() {
return cust_source;
}
public void setCust_source(String cust_source) {
this.cust_source = cust_source;
}
public String getCust_industry() {
return cust_industry;
}
public void setCust_industry(String cust_industry) {
this.cust_industry = cust_industry;
}
public String getCust_level() {
return cust_level;
}
public void setCust_level(String cust_level) {
this.cust_level = cust_level;
}
public String getCust_address() {
return cust_address;
}
public void setCust_address(String cust_address) {
this.cust_address = cust_address;
}
public String getCust_phone() {
return cust_phone;
}
public void setCust_phone(String cust_phone) {
this.cust_phone = cust_phone;
}
}
注意:实体类的编写规范:
1、尽量使用包装类型。
2、建议实现序列化接口。
3、一定要有无参构造方法。
3.5.创建类与表结构的映射
在JavaBean所在的包下创建xml映射文件
映射文件命名规范:实体类名.hbm.xml
在映射文件中引入约束,约束信息从
hibernate-core-5.0.7.Final.jar—>org.hibernate—>/org/hibernate/hibernate-mapping-3.0.dtd中拷贝
如果电脑可以联网,自动从网上下载 DTD,在编写xml文件时就有了提示。
如果不能上网,编写配置文件是没有提示的,需要自己来配置。在实际开发中,都是需要配置本地DTD文件的。配置步骤如下:
第一步:先复制dtd网址:
第二步:然后:window --> Preferences–>XML --> XML Catalog --> Add --> 输入dtd文件所在的路径、Key type选URI、key是dtd文件对应的网址 --> Ok,关闭文件重新打开就有提示啦。
编写映射文件Customer.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> 3.6.编写Hibernate的核心配置文件 在src目录下创建核心配置文件hibernate.cfg.xml在xml文件中引入DTD约束,DTD约束的信息可以从hibernate-core.jar中的org.hibernate包中hibernate-configuration-3.0.dtd中复制。(路径同映射文件dtd文件的路径)
在没有网的情况下,编写xml时,没有提示,需要手动配置,配置方法同映射文件的配置
编写核心配置文件,参考官方发布包中的project/etc/hibernate.properties文件
//实例化Configuration的对象
Configuration cfg = new Configuration();
//读取核心配置文件hibernate.cfg.xml
cfg.configure();
//构造SessionFactory
SessionFactory sf = cfg.buildSessionFactory();
//获取Session,类似于JDBC里的Connection
Session session = sf.openSession();
//开启事务
Transaction tx = session.beginTransaction();
//保存
session.save(customer);
//提交事务
tx.commit();
//释放资源
session.close();
sf.close();
}
注意:以后我们在测试hibernate时,经常使用junit来测试,需用引入junit的jar包,在测试方法上加@Test注解,右键,选择junit的方式运行即可。
3.8.入门案例的执行过程
首先创建Configuration类的实例,并通过它来读取并解析配置文件hibernate.cfg.xml。然后创建SessionFactory读取解析映射文件信息。接下来,让SessionFactory提供连接,打开Session,并开启一个事务,之后创建对象,向对象中添加数据,通过session.save()方法完成向数据库中保存数据的操作。最后提交事务,并关闭资源。
4.Hibernate映射文件
<?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.connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- 配置数据库连接地址 -->
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate</property>
<!-- 数据库用户名 -->
<property name="hibernate.connection.username">root</property>
<!-- 数据库密码 -->
<property name="hibernate.connection.password">123456</property>
<!-- 配置数据库方言 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 打印sql语句 -->
<property name="hibernate.show_sql">true</property>
<!-- 格式化sql语句 -->
<property name="hibernate.format_sql">true</property>
<!-- 指定映射文件路径 -->
<mapping resource="cn/itcast/domain/Customer.hbm.xml"/>
</session-factory>
</hibernate-configuration>
4.1.class标签
作用:用来将类与数据库表建立映射关系
name属性:类的全路径
table属性:表名.(类名与表名一致,那么table属性也可以省略)
catalog属性:数据库的名称,基本上都会省略不写
<class name="cn.itcast.domain.Customer" table="cst_customer">
4.2.id标签
用来将类中的属性与表中的主键建立映射,id标签就是用来配置主键的
name属性:类中属性名
column属性:表中的字段名.(如果类中的属性名与表中的字段名一致,那么column可以省略.)
length属性:字段的长度,如果数据库已经创建好了,那么length可以不写。如果没有创建好,生成表结构时,length最好指定。
generator标签:用于指定主键的生成策略,class属性一般取值为native,表示:判断底层数据库类型,如果是mysql,采用自动增长来维护主键;如果是oracle,采用序列来维护主键。
<id name="cust_id">
<!-- generator标签:指定主键的生成策略
class属性:指定具体的主键的生成策略,native:表示根据底层数据库自动来判断,如果是mysql,采用自动增长来维护主键,
如果是oracle,采用序列来维护主键
-->
<generator class="native"></generator>
</id>
4.3.property标签
用来将类中的普通属性与表中的字段建立映射.
name属性:类中属性名
column属性:表中的字段名.(如果类中的属性名与表中的字段名一致,那么column可以省略.)
length属性:字段的长度。一般都不需要写。
type属性:数据类型(一般都不需要编写,如果写需要按着规则来编写)
Hibernate的数据类型 type=“string”
Java的数据类型 type=“java.lang.String”
数据库字段的数据类型
5.Hibernate核心配置文件
5.1.核心配置的两种方式
第一种方式是属性文件的形式,即properties的配置文件
hibernate.properties
hibernate.connection.driver_class=com.mysql.jdbc.Driver
hibernate.connection.url=jdbc:mysql://localhost:3306/hibernate
hibernate.connection.username=root
hibernate.connection.password=123456
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.show_sql=true
hibernate.format_sql=true
缺点:不能加载映射的配置文件,需要手动编写代码去加载
第二种方式是XML文件的形式,开发基本都会选择这种方式。优点如下:
格式比较清晰
编写有提示
可以在该配置文件中加载映射的配置文件(最主要的)
5.2.关于hibernate.cfg.xml文件的配置方式
必须有的配置
数据库连接信息
数据库方言
可选的配置
hibernate.show_sql:显示sql语句
hibernate.format_sql:格式化sql语句
hibernate.hbm2ddl.auto:通过映射转成DDL语句,可以取如下四个值:
i.create:每次加载hibernate时,如果有表,先删除表,再创建一个新的表
ii.create-drop:每次加载hibernate时,如果有表,先删除表,再创建一个新的表,当SessionFactory关闭后,将创建的这个表删除
iii.update:如果有表,使用原来的表,同时更新表结构.没有表,创建一个新的表。一般取这个值。
iv.validate:如果有表,使用原来的表.同时校验映射文件与表中字段是否一致如果不一致就会报错。
加载映射文件,如果是xml格式的映射文件
6.Hibernate中API介绍
6.1.Configuration类
6.1.1.作用
Configuration对象用于配置并且启动Hibernate。
Hibernate应用通过该对象来获得对象-关系映射文件中的元数据,以及动态配置Hibernate的属性,然后创建SessionFactory对象。
简单一句话:加载Hibernate的核心配置文件,可以获取SessionFactory对象。
Configuration类的其它作用
a)加载配置文件的种类,Hibernate支持xml和properties类型的配置文件,在开发中基本都使用XML配置文件的方式。
b)如果采用的是properties的配置文件,那么通过Configuration configuration = new Configuration();就可以加载配置文件。但是需要自己手动加载映射文件,例如
c)如果采用的XML的配置文件,通过Configuration configuration = new Configuration().configure();加载配置文件
6.1.2.常用方法
默认构造函数:
它只能加载类的根路径下,名称为hibernate.properties的配置文件。不能加载xml
configure():
它用于加载类的根路径下,名称为hibernate.cfg.xml的配置文件。
buildSessionFactory():
根据配置文件,构建SessionFactory
addResource(String url);
指定映射文件的位置
addClass(Class clazz);
指定实体类的字节码。提示:后期注解会用到。
6.2.SessionFactory接口
6.2.1.作用
SessionFactory 实例是通过Configuration对象获取的,其获取方法如下所示。
SessionFactory sessionFactory = config.buildSessionFactory();
总结:一般应用使用一个SessionFactory,最好是应用启动时就完成初始化。
6.2.2.常用方法
openSession():每次都是生成一个新的Session
getCurrentSession():获取当前线程的Session
6.3.编写HibernateUtils的工具类
/**
-
Hibernate的工具类:创建SessionFactory,获取Session
-
@author kevin
*/
public class HibernateUtils {private static final SessionFactory sf;
static{
sf = new Configuration().configure().buildSessionFactory();
}/**
-
获取Session的工具方法
-
@return
/
public static Session openSession(){
return sf.openSession();
}
}
Hibernate工具类的用法:
/* -
HibernateUtils工具类的用法
*/
@Test
public void test4() {
Customer customer = new Customer();
customer.setCust_name(“乐视”);Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();session.save(customer);
tx.commit();
session.close();
}
6.4.SessionFactory中使用数据库连接池(数据源)
SessionFactory内部还维护了一个连接池,如果我们需要使用第三方的连接池如C3P0,那么需要我们自己手动进行配置。
配置C3P0数据库连接池的步骤如下:
导入C3P0所需的jar包
-
在hiberante核心配置文件中配置
测试:能看到如下日志信息,则表示c3p0数据库连接池配置成功
6.5.Session接口
6.5.1.作用
(1)概述
a)Session是在Hibernate中使用最频繁的接口。也被称之为持久化管理器。它提供了和持久化有关的操作,比如添加、修改、删除、加载和查询实体对象
b)Session 是应用程序与数据库之间交互操作的一个单线程对象,是 Hibernate 运作的中心
c)Session是线程不安全的
d)所有持久化对象必须在 session 的管理下才可以进行持久化操作
e)Session 对象有一个一级缓存,显式执行 flush 之前,所有的持久化操作的数据都缓存在 session 对象处
f)持久化类与 Session 关联起来后就具有了持久化的能力
(2)特点
a)不是线程安全的。应避免多个线程使用同一个Session实例
b)Session是轻量级的,它的创建和销毁不会消耗太多的资源。应为每次客户请求分配独立的Session实例
c)Session有一个缓存,被称之为Hibernate的一级缓存。每个Session实例都有自己的缓存
6.5.2.常用方法
save(Object entity); :保存一个实体到数据库
update(Object entity);:更新一个实体
delete(Object entity);:删除一个实体
get(Class clazz,Serializable id);:根据id查询一个实体。参数的含义:Class表示要查询的实体类字节码。Serializable就是查询的条件。
beginTransaction();:开启事务,并返回事务对象
load(Class clazz,Serializable id):根据id查询一个实体。参数的含义:Class表示要查询的实体类字节码。Serializable就是查询的条件。
save(obj) 保存数据
/**
* 保存客户
/
@Test
public void test3(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Customer customer = new Customer();
customer.setCust_name(“小丽”);
customer.setCust_industry(“旅游”);
customer.setCust_source(“电话营销”);
customer.setCust_level(“VIP客户”);
customer.setCust_address(“上海静安区”);
customer.setCust_phone(“13738903304”);
session.save(customer);
tx.commit();
session.close();
}
get(Class clazz,Serializable id) 根据id查询一个实体
/*
* 根据id查询客户
/
@Test
public void test4(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
//根据id查询客户
Customer customer = session.get(Customer.class, 9L);
System.out.println(customer);
tx.commit();
session.close();
}
delete(obj) 删除数据
/*
* 删除客户
*/
@Test
public void test5(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
//根据id查询客户
Customer customer = session.get(Customer.class, 9L);
//删除客户
session.delete(customer);
tx.commit();
session.close();
}
update(obj) 修改数据
/**
* 修改数据
/
@Test
public void test7(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
//根据Id查询客户
Customer customer = session.get(Customer.class, 7L);
//修改客户信息
customer.setCust_phone(“8650123”);
//更新客户
session.update(customer);
tx.commit();
session.close();
}
saveOrUpdate(obj) 保存或修改数据
/*
* saveOrUpdate方法:
* 1、没有指定id,就保存
* 2、如果有id,能对应到表里的数据,就是更新
* 3、如果有id,表里没有记录与之对应,报错
*/
@Test
public void test6(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Customer customer = new Customer();
customer.setCust_id(6L);
customer.setCust_name(“乐视”);
session.saveOrUpdate(customer);
tx.commit();
session.close();
}
6.6. Transaction接口
6.6.1.作用
Transaction接口主要用于管理事务,它是Hibernate的数据库事务接口,且对底层的事务接口进行了封装。Transaction接口的事务对象是通过Session对象开启的,其开启方式如下所示。
Transaction transaction = session.beginTransaction();
6.6.2.常用方法
commit():提交事务
rollback():回滚事务
Session执行完数据库操作后,要使用Transaction接口的commit()方法进行事务提交,才能真正的将数据操作同步到数据库中。发生异常时,需要使用rollback()方法进行事务回滚,以避免数据发生错误。因此,在持久化操作后,必须调用Transaction接口的commit()方法和rollback()方法。如果没有开启事务,那么每个Session的操作,都相当于一个独立的操作。
6.7.实体查询的两个方法
6.7.1.实体查询的概念
所谓实体查询即OID查询,就是使用主键作为条件来查询一个实体。其中涉及的方法是Session对象get方法和load方法。
6.7.2.方法的说明
get方法:
/**
* 根据id查询一个实体
* @param entityType 指的是要查询的实体类字节码对象
* @param id 查询的条件,即主键的值。
* @return 返回的是实体类对象
/
T get(Class entityType, Serializable id);
get方法的代码演示:
/*
* 使用get方法查询id为9的客户
/
@Test
public void test4(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
//根据id查询客户
Customer customer = session.get(Customer.class, 9L);
System.out.println(customer);
tx.commit();
session.close();
}
load方法:
/*
* 根据id查询一个实体
* @param theClass 指的是要查询的实体类字节码
* @param id查询的条件,即主键的值。
* @return 返回的是实体类对象或者是实体类对象的代理对象
/
T load(Class theClass, Serializable id);
load方法的代码演示:
/*
* 使用load方法查询id为9的客户
*/
@Test
public void test9(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Customer customer = session.load(Customer.class, 9L);
System.out.println(customer.getCust_name());
tx.commit();
session.close();
}
问题:既然两个方法都是根据ID查询一个实体,他们有什么区别呢?
6.7.3.get和load的区别
区别:
1、查询的时机不一样
get方法任何时候都是立即加载,即只要一调用get马上发起数据库查询
load方法默认情况下是延迟加载,即真正用到对象的非OID字段数据才发起查询
load方法可以通过配置的方式改为立即加载。
配置的方式:
2、返回的结果不一样
get方法永远返回查询的实体类对象。
load方法当是延迟加载时,返回的是实体类的代理对象。
涉及的概念:
立即加载:
是不管用不用马上查询。
延迟加载:
等到用的时候才真正发起查询。