Hibernate 框架 学习笔记

一、Hibernae的学习路线


二、Hibernate的概述

框架概述:EE经典架构

Hibernate 框架 学习笔记_第1张图片

 EE三层结构(web 层 业务层 持久层)

Hibernate 框架 学习笔记_第2张图片


三、Hibernate的入门

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 框架 学习笔记_第3张图片

Hibernate 优点:

Hibernate 框架 学习笔记_第4张图片


1.编写测试类

Hibernate 环境搭建:下载Hibernate5 

 

Hibernate 版本下载
Hibernate3.x 旧版  
Hibernate4.x 过渡版本  
Hibernate5.x 【官网下载地址】 【-5.0.7-百度云下载地址】【提取码:hgp0】

 

 

 

 

Hibernate 环境搭建:解压Hibernate5

Hibernate 框架 学习笔记_第5张图片

Hibernate 环境搭建:创建第一个项目

步骤:

  1. 引入jar包
  2. 创建表
  3. 创建实体类
  4. 创建映射(类.hbm.xml)(和类在同一个文件夹下)
  5. 创建核心配置文件(hibernate.cfg.xml)(在src目录下)
  6. 编写测试类

分步图示:

1、引入jar包:【jar包百度云:2vyd】

Hibernate 框架 学习笔记_第6张图片

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的一个小例子


2.配置文件的配置

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

 

Hibernate 框架 学习笔记_第7张图片

映射的配置

【class 标签的配置】:标签用来建立类与表的映射关系

  • name :类的全路径
  • table :表名(类名与表名一致,table可省略)
  • catalog :数据库名

【id 标签的配置】:标签用来建立类中属性与表中主键的对应关系

  • name :类中的属性名
  • column :表中的字段名(属性名和字段名一致。column可省略)
  • length :长度
  • type :类型(类型分为三种:java hibernate  sql)

【property标签的配置】:标签用来建立类中的普通属性与表的字段的对相应关系

  • name :类中的属性名
  • column :表中的字段名
  • length :长度
  • type :类型
  • not-null :设置非空
  • unique :设置为一

核心的配置

  • 核心配置的方式
  1. 属性文件:hibernate.properties 属性文件不能引入映射文件需编写代码加载映射文件
  2. XML文件:hibernate.cfg.xml
  • 必须的配置
  1. 连接数据库的基本参数
  2. 驱动类、url路径、用户名、密码
  3. 方言
  • 可选的配置
  1. 显示SQL :hibernate.show_sql
  2. 格式化SQL :hibernate.format_sql
  3. 自动建表 :hibernate.hbm2ddl.auto

none :不使用hibernate的自动建表

creat :如果数据库中已经有表,删除原有表,重新创建,如果没有标,新建表(测试)

creat-drop :如果数据库中已经有表,删除原有表,执行操作,删除这个表。如果没有表,新建一个。使用完了删除该表(测试)

update :如果数据库中有表,使用原有表,如果没有表,创建新表(更新表结构)

validate :如果没有表,不会创建表,只会使用数据库中存在的表(校验映射和表结构)

  • 映射的配置:引入映射文件的位置

四、Hibernate的常见配置

 


1.XML的提示的配置

 


2.映射的配置

 


3.核心配置

 


五、Hibernate的核心API

 


1.Configuration

 


2.SessionFactory

 


3.Session 

 


4.Transaction

 


六、Hibernate持久化类的编写的规则

 


七、Hibernate主键生成策略

 


1.生成策略概述

 


2.生成策略演示

 


八、Hibernate持久化类的三种状态

 


1.认识三种状态

 


2.三种状态的转换

 


3.持久态对象特性

 


九、Hibernate的一级缓存

 


1.一级缓存的概述

 


2.一级缓存的快照区

 


十、Hibernate事务管理

 


1.事务的回顾

 


2.线程绑定的

 


十一、Hibernate的其他的API

 


十二、Hibernate表与表之间关系的分析

 


十三、Hibernate的一对多关系的配置

 


1.创建实体和映射

 


2.编写测试

 


十四、Hibernate的一对多关系的操作

 


1.级联保存或更新

 


2.对象导航的测试

 


3.级联删除

 


4.inverse的配置

 


十五、Hibernate多对多关系的配置

 


1.创建实体和映射

 


2.编写测试代码

 


十六、Hibernate多对多关系的操作

 


1.级联保存

 


2.级联删除

 


3.其他操作

 


十七、Hibernate的查询方式

 


1.OID和对象导航检索

 


2.数据初始化

 


3.HQL查询


i.简单查询和别名查询


ii.排序查询和条件查询


iii.投影查询和分页查询


iv.分组统计查询

 


4.QBC查询


i.简单查询和排序查询


ii.分页查询和条件查询


iii.统计查询


iv.离线条件查询

 

 

 

2、Hibernate API


Configuration

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:Session工厂

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:类似Connection对象是连接对象

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 方法 的 区别 ?
get 方法 load 方法
采用立即加载,执行这行代码的时候,立即发送sql语句去查询 采用延迟加载(lazy懒加载),执行到这行代码时,不会发送sql语句,当真正使用这个对象的时候才会发送sql语句
查询后返回的是真实对象本身 查询后返回的是代理对象(javassist-3.18.1-GA.jar)利用javassist技术产生的代理
查询一个找不到的对象的时候,返回null 查询一个找不到的对象的时候,返回ObjectNotFoundException

 

 

 

 

 

  • 修改方法

void update(Object obj);

直接创建对象进行修改 先查询再修改(推荐)
Customer customer = new Customer();
        customer.setCust_id(1l);
        customer.setCust_name("ID唯一标识");
        session.update(customer);

          没有赋值的属性将会根据数据库字段属性被置空

Customer customer = session.get(Customer.class,1l);
		customer.setCust_name("0修改");
		session.update(customer);

 

  • 删除方法

void delete(Object obj)

直接创建对象进行删除 先查询再删除(推荐)
Customer customer = new Customer();
		customer.setCust_id(20l);
		session.delete(customer);

 

Customer customer = session.get(Customer.class,19l);
		session.delete(customer);

级联删除

  • 保存或更新

 saveorupdate(Object obj)

Hibernate 框架 学习笔记_第8张图片

Transaction:事务对象

commit()

rollback()


持久化类的编写的规则


持久化类的编写规范

  • 什么是持久化类?

持久化:将内存中的一个对象持久化到数据库中过程。Hibernate框架就是用来进行持久化的框架。

持久化类:一个Java对象与数据库的表建立了映射关系,那么这个类在Hibernate中称为持久化类。

持久化类=Java类+映射文件

  • 持久化类的编写规则

对持久化类提供一个无参数的构造方法Hibernate底层需要使用反射生成实例

属性需要私有化,对私有属性提供public的geth和set方法:Hibernate中获取设置对象的值

对持久化类提供一个唯一标识OID与数据库主键对应:Java中通过对象的地址区分是否是同一对象,数据库中通过主键确定是否是同一个记录,在Hibernate中通过持久化类的OID的属性区分是否是同一个对象。

持久化类中属性尽量使用包装类类型:因为基本数据类型默认是0,那么0就会有很多歧义。包装类类型默认值时null

持久化类不要使用final进行修饰:延迟加载本身就是hibernate一个优化的手段。返回的是一个代理对象(javassist可以对没有实现接口的的类产生代理--使用了非常底层的字节码增强技术,继承这个类进行代理)。如果不能被继承,不能产生代理对象,延迟加载也就失效。load方法和get方法一致


Hibernate主键生成策略:


生成策略概述


主键的分类

自然主键:主键的本身就是表中的一个字段(实体中的一个具体的属性)

创建一个人员表,人员都会有一个身份证号(唯一的不可重复的),使用了身份证号作为主键,这种主键称为时自然主键。

代理主键:主键的本身不是表中必须的一个字段(不是实体中的某个具体的属性)

创建一个人员表,没有使用人员中的身份证号,用了一个与这个表不相关的字段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管理
	}
}

三种状态的转换


Hibernate 框架 学习笔记_第9张图片

  瞬时态对象【】 持久态对象【OID/session】 托管态对象【OID】
获得 Customer customer = new Customer() get()、load()、find()、iterate()

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中提供了两种缓存机制机制:一级缓存、二级缓存。

Hibernate的一级缓存:称为是Session级别的缓存,一级缓存生命周期与Session一致(一级缓存是由Session中的一系列的Java集合构成)一级缓存是自带的不可卸载的。(Hibernate的二级缓存是 SessionFactory级别的缓存,需要配置的缓存)。

Hibernate 框架 学习笔记_第10张图片

/**
 * 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();
		
	}
}

一级缓存的结构:一级缓存快照区


 

 

 


 

你可能感兴趣的:(Java)