框架
生命周期管理
查询定位
配置器
提供静态配置策略。让用户可以控制服务的细节部分。如,资源在哪里等等
- 依赖解析
分析组件之间的依赖关系,实现相互通讯,动态管理
- 不同协议层的通讯支持
与不同的系统(平台)进行通讯,如用JDBC和数据存储数据库,用RMI分布组件
扩展支持
DAO层框架
将查询结果封装为bean类,实现面向对象的操作
对条件查询的自动组合
CRM(customer raletionship management)
概述
功能模块
客户信息管理
联系人管理
商机管理
统计分析
系统管理
综合查询
hibernate
概述
Object relational mapping 对象关系映射
利用描述对象和数据库表之间映射的元数据,自动将java程序中的对象持久化到关系型数据库中
通过操作java对象,完成对数据库的操作
- 持久层框架
- 对jdbc进行轻量化封装,简化代码,减少内存消耗
- 简化dao层编码
- 支持多对多
- 可扩展
配置
POJO模式(plain old java object)
pojo类包含与数据库相关属性,通过get和set方法访问
映射文件
xml文件配置映射
一张表对应一个pojo类
核心配置文件
配置参数
配置参数的来由:hibernate-release-5.0.7.Final\project\etc\hibernate.properties
配置数据库连接和hibernate运行所需要的各个属性的值
数据库连接参数
方言
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> **MySQL5Dialect**
显示sql语句
自动建表:none(默认) create create-drop update validate(不建表,结构不匹配报错)
<property name="hibernate.hbm2ddl.auto"></property>
导入mapping文件
xml与properties对比
- properties文件
- .properties文件主要是以key-value键值对的形式存在。
- .properties只能赋值,不能够进行其他的操作。
- xml文件
- 改变底层配置不需要改变和重新编译代码,只需要修改xml中的属性
- 只有在修改了接口后才需要重新编译。 因为服务器在运行的时候会重新加载web.xml文件。
- mapping resource标签加载映射文件
- .xml文件主要是树形结构。
- .xml格式的文件要比.properties格式的文件更灵活一些
- .xml格式的文件可以有多种操作方法,例如添加一个属性,或者做一些其他的定义等。
运行机制
configuration读取配置
- 读取配置文件
- 创建sessionFactory对象
- properties配置下读取xml映射文件
sessionFactory读取映射
configuration类完成任务
重量级,不能随意创建和销毁
一个数据源对应一个sessionFactory
作用
- 负责hibernate的初始化和建立session对象
- 保存自动生成的sql语句,映射数据和可重复数据
- 保存配置的映射关系,维护二级缓存
- 提供session连接,openSession(手动关闭),getCurrentSession(绑定线程)
- 抽取工具类
原因:重量级资源,一个项目只需要一个
具体业务逻辑不使用SessionFactory
- 重量级的理解
相对于Sesion而言是重量级
一个数据库对应一个SessionFactory
SessionFactory存放了大量预定义的SQL语句以及映射元数据,需要很大的缓存
轻量级是指它的创建和销毁不需要消耗太多的资源,意味着可以在程序中经常创建和销毁session 的对象
session管理持久化对象
- 单线程对象
轻量级
作用
- 开启事务
- 创建pojo对象并添加数据
- 通过save,update,saveOrUpdate方法保存到数据库,delete删除
- get,load根据主键查询
- createQuery和createSQLQuery,条件查询
Transaction管理事务
- beginTransaction
- commit
- rollBack
- 数据库对事务的管理以commit为准,rollback后如果没有关闭,数据库默认commit了
持久化类
提供无参构造,反射生成实例
私有属性,提供get和set方法
- java规范
属性使用包装类Integer\Double等
- 默认值不同, int:0, Integer:null。 数据库里面,0值和null值不同。
oid字段与表主键对应
- 判断是否同一个java对象,使用地址值
- 判断是否同一个持久化对象,使用oid的值
持久化类尽量不用final修饰
- 延迟加载机制中使用动态代理生成代理对象,final修饰无法执行此机制
- hibernate动态代理使用cglib机制,生成的是继承被代理类的代理子类,final类无法被继承
瞬时态
- 与数据库无关
- 仅用于携带数据
- 没有oid
持久态
- 存在oid标识
- 加入到了session缓存中
- session没有关闭
- 事务未提交前变为持久态
- 拥有持久化标识,oid与数据库建立起了关联
- 自动更新数据库
脱管态
- session被关闭
- 持有oid,与数据库关联
- evict方法,清除session中某个对象
- close,关闭session
- clear,清除session中所有对象
三态转换
- new对象(瞬时态)–>session保存(持久态,持有了oid,可以未提交)–>session关闭,托管态
- session通过get方法,直接成为持久态
主键生成策略
主键分类
- 自然主键
- 失去了对主键的控制权
- 代理主键(id)(推荐)
- 使用没有任何意义的一个字段
- 主键参数是serializable类型
- 主键写进数据库执行的是io操作,必定是serializable对象
hibernate的主键策略
increment
- 不能在集群下使用
- 适合代理主键
- 不能在多线程下使用
hibernate内部操作 select max(id) from table,将id+1作为候选主键
identity
- 适合代理主键
- 适合int,long等类型
- 由底层数据库支持,要求底层数据库支持自增长类型。
sequence
- 适合代理主键
- 适合int,long等类型
- 由底层数据库支持,要求底层数据库支持序列类型。
native
- 根据底层数据库自动匹配
- 如果支持identity,匹配identity
- 如果支持sequence,匹配sequence
- 适合int,long等类型,不支持字符串类型
uuid
- 比整数型占用更多空间
- hibernate底层为oid分配uuid,覆盖service或web层指定的oid
assigned
- 适合自然主键,需要手动指定(默认值)
缓存
缓存原理
利用高速存储区域,保存低速存储区域的数据,从而提高访问速度
数据库执行的是io操作,io操作是对硬盘的操作,硬盘操作读写数据比内存操作慢
弊端:高速存储区空间,小于低速存储区
缓存替换算法:
- 先入先出:最先保存的数据,最先被替换。
- 命中优先:查询次数少的(命中率低的),最先被替换
- 命中:缓存的数据被访问一次为命中一次
一级缓存
概述
- Session缓存,第一次从数据库取值,并放入缓存,再次取值由缓存提供,减少对数据库的访问次数
内部结构
缓存区数据放入快照区
commit提交事务,判断缓存区数据与快照区是否相同,不同则执行update方法
代码实现
- map集合存放缓存对象,生命周期与Session相同,key为oid
- close清空缓存
二级缓存
- 生命周期与SessionFactory相同
- 需要手动配置
- 应用程序的缓存
- 可以被应用范围内的所有事务共享访问
- 应用范围的缓存可以使用内存或硬盘作为存储介质
- 缓存的生命周期依赖于应用的生命周期
- 非集群环境下可用
- 集群环境下不使用,用redis代替
事务管理
事物的特性
- 原子性
- 一致性
- 隔离性
- 持久性
事物的并发
- 脏读
- 不可重复读
- 虚读幻读
事物的隔离级别
- readUncommited
- read commited
- repeatable read
- serializable
hibernate管理办法
- 代码操作
- beginTransaction
- commit
- rollback
- 配置事务隔离级别
- hibernate.cfg.xml
管理session
业务层获取传递给dao层
session绑定线程
用ThreadLocal绑定线程的原理:ThreadLocal是一个Thread的本地变量,当一个线程访问到ThreadLocal时,会得到一个独立的ThreadLocal副本,这个副本与线程绑定,再将要与线程绑定的资源,放入这个副本变量的集合中,就实现了资源与线程的绑定 这个办法只能实现线程之间的隔离,不能实现线程之间的通信
- hibernate的绑定办法
- thread
- thread
- getCurrentSession方法获得Session对象
- 事务提交后Session自动关闭
- 再次调用getCurrentSession方法后,获取的是一个新的Session
- jta
- session生命周期与jta绑定
- managed
- 委托程序管理session(如:spring)
- 不需要rollback
- 所有修改,都是针对一级缓存区,没有向数据库发送update/delte/insert 语句
- hibernate调试没有异常才发送sql语句
检索
导航对象图检索
OID检索
利用session的set和load方法加载对象
get和load的区别
get是执行立即发送sql语句,load 方法延迟加载,只有在真正使用数据的时候才发送
HQl语句
- 可以设定查询条件
- 支持投影查询(检索对象部分属性)
- 支持分页查询
- 支持分组查询
- 提供内置聚集函数
- 能够 调用用户定义的sql语句
- 支持嵌套查询
- 支持动态绑定参数
获取hibernate的Session对象
编写HQL语句
session.createQuery
调用Query的set方法设置参数
调用Query的list或uniqueResult方法查询
迫切内连接(fetch关键字)
- 普通内连接将查询的数据进行一层封装,返回集合元素为多个对象的数组
- 迫切内连接将查询的数据进行多层封装,将从对象放入主对象的集合中
- select distinct x from Department x inner join fetch x.employees
- 手动去重distinct
迫切左外连接
- from Product p left outer join fetch p.category where p.category.cid=1
QBC(query by criteria)
- 完全面向对象
- hibernate核心查询对象
- 主要针对单表操作
- 离线条件检索(detachedCriteria)
- 可以在其他层生成DetachedCriteria对象,封装数据,向下传递参数
- DetachedCriteria中的约束条件添加后不会自动清除,需要手动置为null
- ObjectOutputStream方法实现detachedCriteria的克隆效果
获取Session
获取criteria
Restriction静态创建criterion条件对象
add方法向criteria中添加criterion
Projects静态创建聚合函数对象
setProjection方法向criteria中添加Project
Order静态创建Order对象
addOrder方法向criteria中添加Order
list或uniqueResult方法查询
SQL查询
- 手动封装java对象
- addEntity
- 用于使用底层数据库的sql方言,生成特殊sql语句
映射关系
一对一
class A{
B b;
}
class B{
A a;
}
一对多
- 实例关系
Class A{
Set(B) bs;
}
Class B{
A a;
}
映射文件
<Set>标签 <set name = "linkmans"> <key column="lkm_cust_id"></key>column描述外键 <one-to-many class="cn.itcast.hibernate.domain.Linkman"></>class属性描述关联类 <set>
多对多
- 不建议使用联合主键,使用没有意义的字段/(代理主键)
- 实例关系
Class A{
Set(B) bs;
}
Class B{
Set(A) as;
}
映射文件
“`
标签
table中间表
column对象在中间表中外键的名称
list和set的选用
- list映射中要求提供index标签column字段(id),进行count查询时,hibernate默认查询的是max(id)+1
- list映射自动生成表时,会将代理主键id与某个外键作为联合主键
- Set集合无序(符合数据库特点),不重复
- list在配置文件中要求配置索引列,该字段如果是主键,而有多个list执行了保存,则会出现索引重复异常(线程问题)
级联操作
curd操作,配置cascade属性
- 级联查询
- 配置一对多\多对多关系之后,自动级联查询,配置延迟加载会暂缓sql语句的发送
- 级联保存
- cascade配置:save-update
- 级联删除
- cascade配置:delete
- 直接发送delete的sql语句
- 如果有外键关联,需要先get/load获得完整对象
外键维护
- inverse:true放弃,false不放弃
- 双向外键维护导致进行了两次维护
- 一对多,一表放弃维护
- 多对多,主动方维护外键,被动方放弃外键维护权
- 放弃外键维护结果
- 一对多:一方保存,多方不生成外键
- 多对多:一方保存,不生成中间表
- 多方(未放弃外键维护权)不受影响
抓取策略
关联对象的抓取策略
- set标签
- fetch的取值:抓取策略
- select.默认值,发送普通的select语句
- join:发送迫切左外联接去查询(lazy失效)
- subselect。发送一条子查询语句查询其关联对象.(查询多个对象,才能体现)
- fetch的取值:抓取策略
- many-to-one标签
- fetch的取值:
- select.默认值,发送普通的select语句
- join:发送迫切左外联接去查询
- 注意:1的一方的配置先取消
- fetch的取值:
延迟加载(lazy load)
延迟加载定义
在真正需要数据的时候,才执行数据加载操作。
Hibernate从数据库获取某一个对象数据\对象的集合属性值\所关联的另一个对象时,创建一个代理对象来代表这个对象
这个对象上的所有属性都是默认值;
只有在真正需要使用该对象的数据时才创建这个真实对象,真正从数据库中加载它的数据,
- 类级别的延迟加载
- 查询某个对象时,是否延迟,标签上配置lazy属性,默认值是:ture,默认延迟加载。
- 一般采用默认值,如果使用立即加载,调用get()方法即可。
- 关联级别的延迟加载
- 查询一个对象的关联对象时,是否延迟。在或上配置延迟。
- hibernate关联对象默认采用延迟加载。可以避免一些无谓的性能开销
- many-to-one标签
- lazy的取值:
- proxy。默认值,是否延迟取决于一的一方类上lazy属性
- false.不采用延迟加载
- no-proxy:不用研究
- set标签
- lazy的取值:
- true。默认值,采用延迟加载
- false.不采用延迟加载
- extra. 极其懒惰的
抓取策略和延迟加载的区别
fetch: 抓取策略。确定查询关联对象,使用那种方式(SQL语句)
lazy: 延迟加载。确定什么时候发送SQL语句,查询关联对象
批量抓取
- batch-size
- 底层sql语句变成了select * from table where column in(?,?);