持久化类的编写规则
主键生成策略
持久化类的三种状态
Hibernate的一级缓存
Hibernate的事务管理
1.持久化类编写规则
什么是持久化类?
-
持久化:将内存中的一个对象持久化到数据库的过程
Hibernate框架就是用来进行持久化的框架. -
持久化类:一个Java对象与数据库的表建立了映射关系,那么这个类在Hibernate中称为持久化类
持久化类编写规则
- 提供一个无参数的构造方法,
- 属性私有, 对私有属性提供public的get和set方法
- 对持久化类提供一个唯一的OID与表主键对应(java中通过对象的地址区分是否同一个对象,在Hibernate中通过持久化类的OID属性来区分是否同一个对象)
- 持久化类中的属性尽量使用包装类(比如Integer…)数据类型
–>(因为基本数据类型默认是0,那么0会有歧义,没有插入为0,难以区分是未插入还是插入值0,包装类类型默认为null,没有插入值为null) - 持久化类不要使用final进行修饰,final修饰的类不能被继承(懒加载是Hibernate一个优化的手段,返回的是一个代理对象(javassist–可以对没有实现接口的类产生代理—,使用的是底层的字节码增强技术,继承这个类进行代理),
<id name="cust_id" column="cust_id">
<generator class="native"></generator>
</id>
2. 主键生成策略
主键的分类
- 自然主键
主键本身就是表中的一个字段,实体中的一个具体属性(例如人员表中的身份证号) - 代理主键
- 主键的本身不是表中的一个字段(不是实体中的某个具体的属性)
实际开发中,尽量使用代理主键
一旦主键参与到业务逻辑中,后期有可能需要修改源代码
好的程序设计满足OCP原则==对程序的扩展是open的
对修改源码是close的
主键的生成策略
在实际开发中,不允许用户手动设置主键,一般将主键交给数据库自动增长,或手写代码进行设置(UUID)
在Hibernate中为减少程序的编写,设置了多种主键生成策略
-
increment : hibernate中提供的自动增长机制,适用于short, int,long类型的主键,在单线程程序中使用.首先发送一条语句select max(id) from 表, 然后让id+1作为下一条记录的主键(存在线程安全问题)
-
identity:适用于short, int,long类型的主键,使用的是数据库底层的自动增长机制,适用于有自动增长的数据库(oracle是没有自动增长的)
-
sequence
适用于short, int,long类型的主键,采用的是序列的方式(oracle支持序列),mysql不能使用sequence -
uuid
适用于字符串类型主键, -
native
本地策略, 可以在identity和sequence之间进行自动切换 -
assigned
hibernate放弃外键的管理,需要手动编写程序 -
foreign外部的,会在一对一的关联映射情况下使用(了解)
3. Hibernate的持久化类的三种状态
Hibernate是持久层框架,通过持久化类完成ORM操作,
持久化类=java类+映射
为了更好的管理持久化类,将持久化类分成三种状态
- 瞬时态(Transient):这种对象没有唯一标识OID,没有被session管理
- 持久态(Persistent):有唯一标识OID,已经被session管理
- 脱管态(Detached)(游离态):有唯一标识OID,没有被session管理
如何区分?
状态转换:(了解)
-
瞬时态对象(没有唯一标识OID,没有被session管理)
获得:Customer customer = new Customer(); //瞬时态的对象,没有唯一的OID,没有被session管理
瞬时态–>持久态 save(Object obj), saveOrUpdate()
瞬时态–>托管态 customer.setCust_id(1) -
持久态对象(有唯一标识OID,已经被session管理)
获得 get(),load(),find(),iterate()
Customer customer =session.get(Customer.class,1l) ;
状态转换
持久–>瞬时: delete()
持久–>脱管 close(),clear(),evict(Object obj) -
脱管态对象(有唯一标识OID,没有被session管理)
获得
Customer customer = new Customer();
customer.setCust_id(1);
状态转换
脱管–>持久
update().saveOrUpdate()
脱管–>瞬时 customer.setCust_id(null);
4. hibernate的一级缓存
持久态对象特性
- 自动更新数据库(底层原理:基于hibernate的一级缓存)
什么是缓存?缓存是一种优化的方式,将我们的一些数据存入内存中,使用的时候直接从缓存中获取,
hibernate提供了两种缓存的机制
- 一级缓存,称为是session级别的缓存,一级缓存生命周期与Session一致,一级缓存是自带的,不可卸载的
- 二级缓存,是SessionFactory级别的缓存,需要配置,企业开发一般不用,用redis等替代
Hibernate的一级缓存的结构
一级缓存中特殊区域:快照区
- 比较缓存区和快照区的数据:
一致–>不更新数据库
不一致–>更新数据库
一级缓存清空:
session.clear();//清空所有
session.evict(customer)
5.事务
事务指的是逻辑上的一组操作,组成这组操作的各个逻辑单元要么全部成功,要么全部失败,
事务的特性:原子性,一致性,隔离性,持久性
如果不考虑隔离性,引发安全性问题
- 读问题
脏读,(读到另一个事务未提交的数据)
不可重复读,(读到另一个事务已经提交的update数据,导致前一个事务多次查询结果不一致)
虚读(读到另一个事务已经提交的insert数据,导致前一个事务多次查询结果不一致) - 写问题(了解)
引发两类丢失更新
读问题的解决
设置事务的隔离级别
read uncommitted 以上读问题都会发生
read committed 解决脏读,但不可重复读和虚读有可能发生
repeatale read 解决脏读和不可重复读,但是虚读有可能发生
serializable 解决所有读问题
Hibernate中设置事务隔离级别
在核心配置文件中配置
<property name="hibernate.connection.isolation">4</property>
Hibernate解决Service事务–>采用的是线程绑定的方式:
Hibernate框架内部已经绑定好了ThreadLocal,
- 在SessionFactory中提供了一个方法 getCurrentSession()
package com.by.utils;
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();
}
public static Session getCurrentSession() {
return sf.getCurrentSession();
}
}
- 通过一个配置完成(核心文件)
<!-- 配置当前线程绑定的Session -->
<property name="hibernate.current_session_context_class">thread</property>
与线程绑定的session,不需要关闭session
总结
Hibernate的持久化类的编写规则
- 无参数构造
- 属性私有
- 属性尽量使用包装类
- 提供一个唯一OID与主键对应
- 不要使用final修饰
Hibernate的主键生成策略
- 主键分类
自然主键
代理主键 - 主键生成策略
increment
identity
sequence
uuid
native
assigned
foreign
Hibernate的持久化类的三种状态
瞬时态:没有唯一标识OID,没有被session管理
持久态:有唯一标识OID,已经被session管理
脱管态:有唯一标识OID,没有被session管理
状态转换:(了解)
Hibernate的一级缓存
一级缓存:Hibernate优化手段,称为是session级别缓存。
一级缓存:快照区
Hibernate的事务管理
事务的回顾
事务的概念
事务的特性
引发安全性问题
安全性问题解决
Hibernate解决读问题
在核心配置文件中 设置隔离级别
Hibernate解决Service事务采用的是线程绑定的方式:
Hibernate的其他的API
Query :HQL 面向对象方式的查询。
Criteria :QBC 完全面向对象化,看不到查询语句。
SQLQuery :SQL查询