无
框架概述:EE经典架构
EE三层结构(web 层 业务层 持久层)
Hibernate是什么?
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的JaveEE架构中取代CMP,完成数据持久化的重任。[引用自百度百科]
总结:Hibernate就是一个持久层的ORM框架,它的存在就是通过建立Java对象和关系型数据库的映射关系以达到简化持久层的设计。
ORM是什么?
Object Relational Mapping (对象关系映射):指的是将一个Java中的对象与关系型数据库的表建立一种映射关系,从而操作对象就可以操作数据库中的表
Hibernate 优点:
Hibernate 环境搭建:下载Hibernate5
Hibernate3.x | 旧版 | |
Hibernate4.x | 过渡版本 | |
Hibernate5.x | 【官网下载地址】 | 【-5.0.7-百度云下载地址】【提取码:hgp0】 |
Hibernate 环境搭建:解压Hibernate5
Hibernate 环境搭建:创建第一个项目
步骤:
- 引入jar包
- 创建表
- 创建实体类
- 创建映射(类.hbm.xml)(和类在同一个文件夹下)
- 创建核心配置文件(hibernate.cfg.xml)(在src目录下)
- 编写测试类
分步图示:
1、引入jar包:【jar包百度云:2vyd】
2、创建表(``反引号)
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_sphone` VARCHAR(64) DEFAULT NULL COMMENT '固定电话',
`cust_mobile` VARCHAR(16) DEFAULT NULL COMMENT '移动电话',
PRIMARY KEY (`cust_id`)
)ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
3、创建实体类
package com.itheima.domain;
/**
* 客户管理的实体类
* @author 93615
*
*/
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_phone;
private String cust_mobile;
--省略get/set--
}
4、创建映射文件( “类.hbm.xml” )
错误描述:org.hibernate.boot.InvalidMappingException: Could not parse mapping document: com/itheima/hibernate/demo1/Customer.hbm.xml (RESOURCE) 。
问题所在:少了个反斜杠。
错误分析:错误提示只能定位到这个文件一直知道是映射不成功,看映射地址和类名、表名都没问题。突然看到少个反斜杠一试就没有Error了(错误提示中Caused by 会给一个坐标 一定程度上会给一些帮助 去纠错) 。
5、创建核心配置文件(hibernate.cfg.xml)
com.mysql.jdbc.Driver
jdbc:mysql:///hibernate01
root
root
org.hibernate.dialect.MySQLDialect
true
true
update
6、编写测试类
package com.itheima.domain;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
public class HibernateDemo01 {
@Test
public void demo01(){
//1、加载Hibernate的核心配置文件
Configuration configuration = new Configuration().configure();
//2、创建一个SessionFactory对象:类似于JDBC的连接池
SessionFactory sessionFactory = configuration.buildSessionFactory();
//3、通过SessionFactory创建一个Session对象:类似于JDBC的Connection
Session session = sessionFactory.openSession();
//4、手动开启事务
Transaction transaction = session.beginTransaction();
//5、编写代码
Customer customer = new Customer();
customer.setCust_name("张勇帅");
session.save(customer);
//6、关闭事务
transaction.commit();
//7、资源释放
session.close();
}
}
以上就是一个Hibernate的一个小例子
1、XML的提示配置
hibernate-mapping-3.0.dtd | hibernate-release-5.2.5.Final\project\hibernate-core\src\main\resources\org\hibernate |
hibernate-configuration-3.0.dtd | hibernate-release-5.2.5.Final\project\hibernate-core\src\main\resources\org\hibernate |
hibernate.properties | hibernate-release-5.2.5.Final\project\etc |
映射的配置
【class 标签的配置】:标签用来建立类与表的映射关系
【id 标签的配置】:标签用来建立类中属性与表中主键的对应关系
【property标签的配置】:标签用来建立类中的普通属性与表的字段的对相应关系
核心的配置
none :不使用hibernate的自动建表
creat :如果数据库中已经有表,删除原有表,重新创建,如果没有标,新建表(测试)
creat-drop :如果数据库中已经有表,删除原有表,执行操作,删除这个表。如果没有表,新建一个。使用完了删除该表(测试)
update :如果数据库中有表,使用原有表,如果没有表,创建新表(更新表结构)
validate :如果没有表,不会创建表,只会使用数据库中存在的表(校验映射和表结构)
Configuration 类的作用是对Hibernate 进行配置,以及对它进行启动。在Hibernate 的启动过程中,Configuration 类的实例首先定位映射文档的位置,读取这些配置,然后创建一个SessionFactory对象。虽然Configuration 类在整个Hibernate 项目中只扮演着一个很小的角色,但它是启动hibernate 时所遇到的第一个对象。
作用:加载核心配置文件
hibernate.properties
Configuration cfg = new Configuration();
heiernate.cfg.xml
Configuration cfg = new Configuration().config();
作用:加载核心配置文件
//手动加载映射
configuration.addResource("com/itheima/domain/Customer.hbm.xml");
SessionFactory接口负责初始化Hibernate。它充当数据存储源的代理,并负责创建Session对象。这里用到了工厂模式。需要注意的是SessionFactory并不是轻量级的,因为一般情况下,一个项目通常只需要一个SessionFactory就够,当需要操作多个数据库时,可以为每个数据库指定一个SessionFactory。
SessionFactory内部维护了Hibernate的连接池和二级缓存时线程安全的对象【一个项目创建一个对象即可】
抽取工具类:
package com.itheima.domain;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
public static final Configuration cfg;
public static final SessionFactory sf;
static{
cfg=new Configuration().configure();
sf= cfg.buildSessionFactory();
}
public static Session openSession(){
return sf.openSession();
}
}
测试工具类:
@Test
public void demo02(){
Session session = HibernateUtil.openSession();
Transaction transaction = session.beginTransaction();
Customer customer = new Customer();
customer.setCust_name("zhangshan");
session.save(customer);
transaction.commit();
session.close();
}
Session接口负责执行被持久化对象的CRUD操作(CRUD的任务是完成与数据库的交流,包含了很多常见的SQL语句)。但需要注意的是Session对象是非线程安全的。同时,Hibernate的session不同于JSP应用中的HttpSession。这里当使用session这个术语时,其实指的是Hibernate中的session,而以后会将HttpSession对象称为用户session。
Session代表的是Hibernate与数据库的链接对象。不是线程安全的,与数据库交互桥梁。
Session中的API(ID作为唯一标识)
Serializable save(Object obj);
T get(Class c,Serializable id);
T load(Class c,Serializable id);
get 方法 | load 方法 |
---|---|
采用立即加载,执行这行代码的时候,立即发送sql语句去查询 | 采用延迟加载(lazy懒加载),执行到这行代码时,不会发送sql语句,当真正使用这个对象的时候才会发送sql语句 |
查询后返回的是真实对象本身 | 查询后返回的是代理对象(javassist-3.18.1-GA.jar)利用javassist技术产生的代理 |
查询一个找不到的对象的时候,返回null | 查询一个找不到的对象的时候,返回ObjectNotFoundException |
void update(Object obj);
直接创建对象进行修改 | 先查询再修改(推荐) |
没有赋值的属性将会根据数据库字段属性被置空 |
|
void delete(Object obj)
直接创建对象进行删除 | 先查询再删除(推荐) |
|
级联删除 |
saveorupdate(Object obj)
commit()
rollback()
- 什么是持久化类?
持久化:将内存中的一个对象持久化到数据库中过程。Hibernate框架就是用来进行持久化的框架。
持久化类:一个Java对象与数据库的表建立了映射关系,那么这个类在Hibernate中称为持久化类。
持久化类=Java类+映射文件
- 持久化类的编写规则
对持久化类提供一个无参数的构造方法:Hibernate底层需要使用反射生成实例
属性需要私有化,对私有属性提供public的geth和set方法:Hibernate中获取设置对象的值
对持久化类提供一个唯一标识OID与数据库主键对应:Java中通过对象的地址区分是否是同一对象,数据库中通过主键确定是否是同一个记录,在Hibernate中通过持久化类的OID的属性区分是否是同一个对象。
持久化类中属性尽量使用包装类类型:因为基本数据类型默认是0,那么0就会有很多歧义。包装类类型默认值时null
持久化类不要使用final进行修饰:延迟加载本身就是hibernate一个优化的手段。返回的是一个代理对象(javassist可以对没有实现接口的的类产生代理--使用了非常底层的字节码增强技术,继承这个类进行代理)。如果不能被继承,不能产生代理对象,延迟加载也就失效。load方法和get方法一致
自然主键:主键的本身就是表中的一个字段(实体中的一个具体的属性)
创建一个人员表,人员都会有一个身份证号(唯一的不可重复的),使用了身份证号作为主键,这种主键称为时自然主键。
代理主键:主键的本身不是表中必须的一个字段(不是实体中的某个具体的属性)
创建一个人员表,没有使用人员中的身份证号,用了一个与这个表不相关的字段ID,(PND).这种主键称为时代理主键
在实际开发中,尽量使用代理主键。
一旦自然主键参与到业务逻辑中后期可能需要修改源代码
好的程序设计满足OCP原则,对程序的扩展是open的,对修改源码是close的。
在实际开发中一般是不允许用户手动设置主键,一般将主键交给数据库,手动编写程序进行设置,在Hibernate中提供了很多主键的生成策略
incerment :Hibernate中提供的自动增长机制,使用short、int、long类型的主键。
在单线程程序中使用首先先发送一条语句(select max(id)from 表)然后让ID+1作为吓一跳记录的主键
identity:使用short、int、long类型的主键,使用的是数据库底层的自动增强机制
适用于自动增强机制数据库(Mysql、MSSQL)但是Oracle是没有自动增长
sequence :使用short、int、long类型的主键。采用的是序列的方式。
(Oracle支持序列)像Mysql就不能使用sequence
uuid :适用于字符串类型的主键。使用hibernate中的随机方式生成字符串主键
native :本地策略。可以在identity和sequence之间进行自动切换。
assigned :hibernate放弃主键的管理,需要通过手动编写程序或者用户自己设置
foreign : 外部的。一对一的一种关联映射的情况下使用(两个表主键相同)(了解)
略...
Hibernate是持久层框架,通过持久化类完成ORM操作。Hibernate为了更好地管理持久化类,将持久化类分成了三种状态。
瞬时态:这种对象没有唯一的标识OID,没有被session管理,称为是瞬时态对象。
持久态:这种对象有唯一的标识OID,被session管理,称为是持久态对象。持久化类的持久态对象可以自动更新数据库。
托管态:这种对象有唯一的标识OID,没有被session管理,称为是托管态对象
package com.itheima.domain; 《区分三种状态对象》
import java.io.Serializable;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import com.itheima.utils.HibernateUtil;
/**
*
* Hibernate的持久化类的三种状态
* @author 93615
*
*/
public class HibernateDemo02 {
@Test
public void demo01(){
Session session = HibernateUtil.openSession();
Transaction transaction = session.beginTransaction();
Customer customer = new Customer();// 瞬时态对象,没有唯一标识OID,没有被session管理
customer.setCust_name("小仙女");
Serializable id = session.save(customer);//持久态对象,有唯一标识OID,被session管理
session.get(Customer.class, id);
transaction.commit();
session.close();
System.out.println("客户名称"+customer.getCust_name());//托管态对象,有唯一标识OID,没有被session管理
}
}
瞬时态对象【】 | 持久态对象【OID/session】 | 托管态对象【OID】 | |
获得 | Customer customer = new Customer() | get()、load()、 |
Customer customer = new Customer() customer.setCust_id(1l) |
转换 | 瞬时->持久: save(Object obj) saveOrUpdate(Object obj) |
持久->瞬时: delete() |
托管->持久: update() saveOrUpdate(Object obj) |
转换 | 瞬时->托管: customer.setCust_id(1l)
|
持久->托管: close()、clear()、evict(Object obj) |
托管->瞬时: customer.setCust_id(null) |
saveOrUpdate何时save何时update呢是需要看他的对象状态的,如果对象是瞬时态对象就是save如果是托管态对象就是Update |
持久化类对象的持久态对象可以自动更新数据库
@Test
/**
* 持久态对象自动更新数据库
*/
public void demo02(){
Session session = HibernateUtil.openSession();
Transaction transaction = session.beginTransaction();
//获得持久态对象
Customer customer = session.get(Customer.class, 1l);
customer.setCust_name("love you");
//自动更新数据库 当值不一样时自动更新 值一样时只做查询 原理(底层一级缓存)
transaction.commit();
session.close();
}
缓存:是一种优化的方式,将数据存到内存中,使用的时候直接从缓存中获取,不用通过储存源。
Hibernate框架中提供了优化手段:缓存、抓取策略。
Hibernate中提供了两种缓存机制机制:一级缓存、二级缓存。
Hibernate的一级缓存:称为是Session级别的缓存,一级缓存生命周期与Session一致(一级缓存是由Session中的一系列的Java集合构成)一级缓存是自带的不可卸载的。(Hibernate的二级缓存是 SessionFactory级别的缓存,需要配置的缓存)。
/**
* hibernate证明一级缓存的测试
* @author 93615
*
*/
public class HibernateDemo03 {
@Test
public void demo01(){
Session session = HibernateUtil.openSession();
Transaction transaction = session.beginTransaction();
Customer customer = session.get(Customer.class, 1l); //发送SQL
System.out.println(customer);
Customer customer1 = session.get(Customer.class, 1l); //不发送SQL 从缓存获取数据
System.out.println(customer1);
//查询一次 打印两次
Customer customer2 = new Customer();
customer2.setCust_name("Java");
Serializable id = session.save(customer2);
Customer customer3 = session.get(Customer.class, id);//不发送SQL 从缓存获取
System.out.println(customer3);
transaction.commit();
session.close();
}
}