Hibernate
引入问题:开发的语言是面向对象的,但是在面向数据库操作层面还是面向关系的,因此我们需要手工来做转换工作。
什么是ORM(Object Relation Mapping)
Object:对象,java对象,此处特指JavaBean
Relational:关系,二维表,数据库中的表。
映射|映射元数据:对象中属性,与表的字段,存在对应关系。关于hibernate
纯面向对象来跟数据库交互
1.Hibernate是重量级JavaEE应用的持久层解决方案,是一个关系数据库ORM框架
a)ORM 就是通过将Java对象映射到数据库表,通过操作Java对象,就可以完成对数据表的操作
2.Hibernate提供了对关系型数据库增删改成操作开发步骤
1.创建数据库和表
2.创建对应的实体类
3.导入Hibernate的jar包
4.编写核心配置文件hibernate.cfg.xml
5.编写映射文件*.hbm.xml(和VO放到一起)
使用Hibernate API进行开发关于Jar包难用的问题
eclipse中提供了User Libraries 进行:打开Eclipse,点击工具栏中的window->Preferences,选择左侧中的java->User Libraries,使用的话配置build path->add libraries
第二种就是使用maven项目进行配置。关于eclipse, F1的帮助文档问题需要仔细翻阅, 关于myeclipse比eclipse更为好用
提这点的目的是在于, 想成为优秀程序员之一条件就是提高效率, 用最短的时间做最多的事(学习新的 技术, 知识, 压缩以前做的项目的时间)
5.关于配置信息
关于配置信息主要还是查官网, 官网手册上面写的就是属性可以根据etc文档进行复制, 避免时间的浪费
6.数据库4种语言
DDL(Data Definition Language)数据库定义语言
DML(Data Manipulation Language)数据操纵语言
DCL(Data Control Language)数据库控制语言
TCL(Transaction Control Language)事务控制语言
- 映射文件概图
8.使用API进行编程
- 对象的三种状态
Hibernate规定对象具备三种状态,瞬时状态,持久状态,托管状态
瞬时状态:transient,session没有缓存对象,数据库也没有对应记录
持久状态:persistent,session有缓存对象,数据库有对应的记录
托管状态:detached,session没有缓存对象,数据库也有记录
主键生成策略
1.increment:由Hibernate以递增的方式生成
2.identity:由底层数据库的自增主键生成机制产生,要求底层数据库支持自增字段类型,如mysql的auto_increment和SQL Server的identity
3.sequence:由底层数据库的序列生成机制产生,比如Oracle的序列
4.native:根据底层数据库对自动生成标识符的支持能力来智能选择session的两种创建方式
getCurrentSession(),openSession()
currentSession会先到一级缓存中查找一级缓存又称为session级别的缓存,为优化程序性能,每次获取数据,Hibernate会优先从session缓存中获取,如果有就直接使用,如果没有,再查数据,并将其存储到缓存中。当session关闭,则一级缓存销毁。
一级缓存get&load
get如果获取的是id则会在代理对象中进行查找,而不会直接发送sql语句
13.映射
多表关系
表和表之间存在的关系就是主外键关系,而对象和对象之间通常存在以下三种关系:
一对一,一对多,多对多
我们首先一起来看看表之间是怎么建立这三种关系的。
一对一:(一个人对应一个身份证号)
一对多:(一个客户对应多个订单)
多对多:(老师可以带多个班级,一个班可以被多个老师带)
- hibernate创建步骤为:
1.创建具备一对多关系的表(两张表)
2.创建对应的类,并建立联系(两个类)
3.添加两个类的映射文件
4.编写测试程序,测试增删改查的应用及特点
5.分别建立单向和双向的映射关系观察实验结果
15.控制反转
为什么要用inverse:结果就是节省了update语句,注意要设置Phone跟Person的关系,提升了性能。
所以一对多,一般就是把关系交给多的一方来维护原因:关系由多的一方来维护,表现的就是在插入数据的时候直接建立联系
而不需要再逐个去发送更新语句
- 级联操作
save-update
级联操作主要作用是提高我们的开发效率,我们保存一的一方, 让级联自动去保存多的一方
save-delete
如果这个关系是由一的一方来维护,则会清除掉关联关系,再执行删除
如果这个关系是由多的一方来维护,则会出现外键约束异常
所以当我们将关系交给多的一方来维护时,可以设置级联删除
- 关于删除的时候的场景:
有时候,关系已经交给多的一方来维护,我们要删除的一的一方,但是不想删除多的一方数据,只是去除掉关系,比如一个员工离职了,那他跟其他部门的关系要清除,但是这些部门是不能删除的
这个时候就是不设置级联删除,只能手动进行解除关系,里面是因为级联的时候是通过set类型的属性进行删除, 只要清空set即可
方法总览:
save-update:一的一方保存,同时保存多的一方
delete:删除一的一方,同时删除多的一方
delete-orphan:孤儿删除,解除一和多的关系,同时将多的一方删除
如果需要配置多项,使用逗号分隔。<set cascade="save-update,delete">
all : save-update 和 delete 整合
all-delete-orphan : 三个整合
18.多表建立关系(多对多)
核心配置文件:
api进行操作:
19.抓取策略
检索方式:
- 立即检索:立即查询,在执行查询语句时,立即查询所有的数据。get
延迟检索:延迟查询,在执行查询语句之后,在需要时在查询。load
比如:
get:立即检索。get方法一执行,立即查询所有字段的数据。
load:延迟检索。默认情况,load方法执行后,如果只使用OID的值不进行查询,如果要使用其他属性值将查询。(会受到映射文件的配置影响)
检索级别
1.类级别检索:当前的类的属性获取是否需要延迟。
2.关联级别的检索:当前类 关联 另一个类是否需要延迟。
类的:
关联级别的:
1.容器
- a)fetch:确定sql的语法,以什么样的格式抓取数据。
- b)lazy:确定关联对象是否延迟。
2.fetch:select、join、subselect - a)select:使用多个select语句(默认值)
- b)join:底层使用迫切左外连接
- c)subselect:使用子查询
3.lazy:true、false、extra - a)true:延迟(默认值)
- b)false:立即
- extra:极其懒惰
1.lazy="true",延迟,先查询客户select,需要订单信息时,再查询订单select
2.lazy="false" , 立即加载,先查询客户select,立即查询订单select
3.lazy="extra",极其懒惰(延迟),先查询客户select, 如果需要查订单的时候将会优先用函数进行查询相关操作
- subselect会以子查询的方式来发送查询语句,而select是发送多条select语句
而extra的情况下,两者的表现是一样的- join,后面的lazy设置成什么,结果都一样
- 将产生多条select语句
20. 批量查询
1.当人员 关联查询 手机信息,给每一个客户生产一个select语句查询订单。批量查询使用in语句减少查询订单语句个数。
2.默认:select * from t_order where customer_id = ?
3.批量:select * from t_order where customer_id in (?,?,?,?)
4.hibernate中配置文件进行配置<set batch-size="5">
5表示括号中?个数。
口述总结篇:
1.ORM对象关系映射
- ORM组件有哪些
a)jdbc
- b)hibernate
- c)MyBatis
2.hibernate环境搭建d)SpringData
- 1)导入相关jar包
- 2)配置文件(使用手册里面去找)
a)hibernate.cfg.xml ,配置数据源,
- 2)映射文件
- 1)命名:实体类名.hbm.xml
- 2)位置:和实体类放在一起
- 3)工具类(使用手册里面去找)
- 4)操作数据库的流程
a)获取sessionFactory
- b)通过sessionFactory创建session
- c)开启事务
- d)操作数据库
- e)提交事务
3.主键生成策略
- native
- identify
- sealizetion
4.一级缓存(session级别缓存)
- 1)get
1)先打session缓存中去找,如果找到了就直接返回,没有再发送sql去查询
2)缓存只对当前session有效
5.get&load
- 1)get:
a)调用完后立即查询
b)查询一个不存在的数据,返回的是一个空 - 2)load(懒加载)
a)它返回的是一个代理对象,这个对象中id有值
b)当调用非id属性的时候就会发送sql去查询
c)查询一个不存在的数据直接抛出异常
6.一对多
- 配置文件
- 一的一方
- vo:要保存多的一方的set
配置文件:
name:一的一方中保存多的一方的属性名称
"< key >":配置关联关系
< one-to-many>:配置多的一方的全类名
多的一方
1. vo:要有一的一方的对象
2. 配置文件a)< many-to-one>
name:多的一方中保存一的一方的属性名称
column:做为外键的一个列名称
- 添加
1. 在一对多的情况下关联字段的维护权权限在一的一方
2. 一般情况下维护全要给多的一方
- a)invers=true
- b)在多的一方建立关系
- 查询
1. 查询一个客户的时候用到订单的时候才会去查询 删除
1. 在删除一个有订单的客户要手动解除关系,但是存在垃圾数据事务提交
1. 提交事务
2. 关闭session
3. 当缓存中的数据发送变化的时候会把缓存中的数据刷到数据库
6.级联属性
1. save-update : 保存一的一方多的一方自动保存
2. delete: 删除一的一方同时如果有多的一方也有数据也删除
3. delete-orphan(孤儿删除): 删除和当前对象解除关系的对象
4. 常用的是all(save-update+delete)
1.多对多
>1. 建表开始: 注意组合主键
2. 实体类 :两边都要用set
3. 配置 :
teacher
< set>
1. name:储存另一方的集合名词
2. table:中间表的名称
3. < key>: name:外键名称
4. < many-to-many>
+ 1)calss:另一方的实体类名称
+ 2)column:另一方的外键名称
班级
1)和上面的相反
4.添加
1. 默认是两边都有中间表的维护权限,只要有一方维护就可以。(在维护全的那边建立关系)
2. 级联属性
a)维护权在那边级联属性就加在哪里
b)删除(慎重)
5.抓取策略
1. 类级别的抓取: get&load 懒加载机制,可以控制这种机制。加一个lazy=false
2. 关联级别的抓取(了解)
a)fetch:决定以什么样的方式查询 1)select 2)join 3)subseelct b)lazy:赖的程度 1)true 2)false 3)extra--极其懒惰
6.HQL
- 面向对象的查询语言
- 在hibernate里面查询的
- 可以查询返回一个list
7.批量查询
1)每次查询N个客户的订单
2)在映射文件中的set标签里面加一个batch-size=n
8.HQL
1)面向对象的查询语句 2)只在HIbernate里面有效 3)提供的方法 a)查询一个list 2)query.list() b)查询个单个的对象 1)query.uniqueResult() c)投影:展示部分字段 1)如果展示一个字段的时候用字符串去接收 2)如果展示多个字段的时候用Object数组去接收 3)在HQL可以调用构造器 d)排序 e)分页 f)分组 g)绑定参数 1)问号(?) a)从0开始的 2):属性名称 h)聚合函数 1)不能用*(select count(*)from Customer) 2)返回的结果集用uniqueResult()接收 a)返回的是一个long类型 i)连接查询 1)笛卡尔积效率 a)产生的原因是没有关联条件 2)连接查询
9.命名查询
1)HQL语句放到了映射文件 2)局部命名查询 a)定义:在class节点里面 b)如何调用 1)session.getNameQuery("namespace.class.queryName") 3)全局的命名查询 a)定义:在class节点外面 b)如何调用 1)session.getNameQuery("queryName") 4)HQL语句里面不能出现*号