Hibernate学习笔记02 主键生成策略、一级缓存、事务管理
持久化类概述
什么是持久化类
- 持久化:将程序数据在持久状态和瞬时状态间转换的机制
- 持久化类:一个java对象与数据库的表建立映射关系,则这个类在Hibernate中称为持久化类
- 持久化类 = java类 + 映射文件
持久化类的编写规则
- 对持久化类提供一个无参的构造方法 : Hibernate底层需要使用反射生成实例;
- 属性需要私有化,对私有属性提供public的get和set方法:Hibernate可以获取对象属性或设置对象的属性值;
- 对持久化类提供一个唯一标识OID与数据库主键对应:java中通过对象的地址区分是否为同一个对象,数据库中通过主键确。是否是同一条记录,Hibernate中通过持久化类的OID区分是否为同一个对象;
- 持久化类中属性尽量使用包装类类型:基本数据类型默认是0,但0有很多歧义。包装类类型默认值为Null;
- 持久化类不要使用final进行修饰:load延迟加载是通过继承来生成代理对象的。
主键生成策略
主键的分类
自然主键
解释:主键本身就是表中的一个字段(实体中的一个具体属性)
代理主键
解释:主键的本身不是表中必须的一个字段(不是实体的一个具体属性)
在实际开发中,尽量使用代理主键
自然主键参与到业务逻辑中,后期有可能需要修改源代码
遵循OCP原则,对程序的扩展是open的,对修改源码是close的
生成策略
- increment:hibernate提供的自动增长机制,适用short/int/long类型的主键,在单线程程序中使用
- indenity:适用于short/int/long类型的主键,使用的是数据库底层的自动增强机制(MySQL/MSSQL)
- sequence:适用于short/int/long类型的主键,采用的是序列的方式(Oracle)
- uuid:适用于字符串类型主键,使用Hibernate中的随机方式生成字符串主键
- native:本地策略,可以在indenity和squence之间自动切换
- assigned:hibernate放弃主键管理,需要通过手动编程或者用户自己设置
- foreign:外部的,一对一的一种关联映射的情况先使用(了解)
持久化类的三种状态
Hibernate是持久层框架,通过持久化类完成ORM操作,Hibernate为了更好的管理持久化类,将持久化分成三种状态
瞬时态
这种对象没有唯一的标识OID,没有被session管理,则这种对象成为瞬时态对象
持久态
这种对象有唯一标识OID,被session管理,则这种对象成为持久态对象
管态
这种对象有唯一标识OID,没有被session管理,则这种对象成为托管态对象
如何区分这三种状态
/**
* Hibernate持久类的三种状态
* @version 1.0
* @autho ban
* @date 2019/4/8 9:09
*/
public class HibernateDemo {
public static void main(String[] args) {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
//Customer是一个持久化类,这是一个瞬时态对象,没有唯一标识ID,也没有被session管理
Customer customer = new Customer();
customer.setCust_name("张三");
//得到唯一的标识OID,且被session管理,所以是持久态对象
Serializable id = session.save(customer);
session.get(Customer.class,id);
transaction.commit();
session.close();
//有唯一的标识,但没有被session管理,所以是托管态对象
System.out.println("客户名:" + customer.getCust_name());
}
}
三种状态的转换(了解)
瞬时态
获取:
Customer customer = new Customer();
状态转换:
-
瞬时——>持久
sava(Object obj)、saveOrUpdate(Object obj); -
瞬时——>托管
customer.setCust_id(1l);
持久态
获取:get()、load()、find()、iterate()Customer customer = session.get(Customer.class,1l);
状态转换:
-
持久——>瞬时
delete();扫描二维码关注公众号,回复: 5834381 查看本文章 -
持久——>托管
close()、clear()、evict();
托管态
获取:Customer customer = new Customer(); customer.setCust_id(1l);
状态转换:
-
托管——>持久
update()、saveOrUpdate(); -
托管——>瞬时
customer.setCust_id(null);
持久态对象特性
自动更新数据库
/**
* 持久态对象自动更新数据库
* @version 1.0
* @autho ban
* @date 2019/4/8 9:09
*/
public class HibernateDemo {
public static void main(String[] args) {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
//获取持久态对象
Customer customer = session.get(Customer.class,1l);
customer.setCust_name("lisi")
//不调用update
//session.update(customer)
transaction.commit();
session.close();
}
}
持久态对象之所以能在不调用update的情况下,自动更新数据库是因为它的底层原理基于hibernate的一级缓存
一级缓存
什么是缓存
缓存是一种优化方式,将数据放入缓存中,使用时可以直接从缓存中直接获取,不用通过存储源
Hibernate的一级缓存
Hibernate框架中提供了缓存和抓取策略的优化手段,其中有两种缓存机制:一级缓存、二级缓存
Hibernate的一级缓存称为session级缓存,其生命周期与session一致,再带不可卸载。
Hibernate的二级缓存称为SessionFactory级缓存,需要配置的缓存,目前基本不用。
/**
* HIbernate的一级缓存测试
* @version 1.0
* @autho ban
* @date 2019/4/8 9:09
*/
public class HibernateDemo {
public static void main(String[] args) {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
/*
//发送SQL语句
Customer customer01 = session.get(Customer.class,1l);
System.out.println(customer01);
//不发送SQl语句
Customer customer02 = session.get(Customer.class,1l);
System.out.println(customer02)
Systme.out.println(customer01 == customer02)
*/
Customer customer = new Customer();
customer.setCust_name("zhangsan");
Serializable id = session.save(customer);
Customer customer03 = session.get(Customer.class,id);
System.out.println(customer03);
transaction.commit();
session.close();
}
}
Hibernate一级缓存的结构
快照区
/**
* HIbernate的一级缓存的快照区
* @version 1.0
* @autho ban
* @date 2019/4/8 9:09
*/
public class HibernateDemo {
public static void main(String[] args) {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Customer customer = session.get(Customer.class,1l);
customer.setCust_name("wangwu");
transaction.commit();
session.close();
}
}
一级缓存的清空
/**
* HIbernate的一级缓存的清空
* @version 1.0
* @autho ban
* @date 2019/4/8 9:09
*/
public class HibernateDemo {
public static void main(String[] args) {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Customer customer1 = session.get(Customer.class,1l);//发送SQL语句查询,同时放入一级缓存
//清空所有缓存
//session.clear();
//清空制定
session.evite(customer1);
Customer customer2 = session.get(Customer.class,1l);//发送SQL语句查询
System.out.println(customer1);
System.out.println(customer2);
transaction.commit();
session.close();
}
}
Hibernate的事务管理
事务的回顾
什么是事务
事务指的是逻辑上的一组操作,组成这组操作的逻辑单元要么全部成功,要么全部失败。
事务的特性
- 原子性:代表事务不可分割
- 一致性:代表事务执行的前后,数据的完整性保持一致
- 隔离性:代表一个事务在执行过程中,不应该受到其他事务的干扰
- 持久性:代表事务执行完成后,数据持久到数据库中
安全性问题
- 读的问题
*脏读:一个事务读到另一个事务未提交的数据
*不可重复读:一个事务读到另一个事务已经提交的update数据,导致在前一个事务多次查询结果不一致
*虚读:一个事务读到另一个事务已经提交的insert数据,导致在前一个事务多次查询结果不一致 - 写的问题
*引发两类丢失更新
问题解决方案
- 读问题
1.设置事务的隔离级别
Read uncommitted:以上读问题都会发生
Read committed:解决脏读,但其余读问题有可能发生
Repeatable read:解决脏读和不可重复读,但虚读有可能发生
Seriallzable:解决所有读问题
设置事务隔离级别
<property name="hibernate.connection.isolation">4</property>
service层事务
Hibernate解决Service的事务管理
- 改写工具类
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/**
* @version 1.0
* @autho ban
* @date 2019/4/8 15:16
*/
public class HibernateUtils {
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();
}
}
- 配置完成
<property name="hibernate.current_session_context_class" >thread</property>
thread:Session对象的生命周期与本地线程绑定
jta:Session对象的生命周期与JTA事务绑定
managed:Hibernate委托程序来管理Session对象的生命周期
Hibernate其他的API
Query
Query接口用于接收HQL,查询多个对象
- HQL(Hibernate Query Language): Hibernate查询语言,与SQL的语法极其相似,面向对象查询的语言。
import net.zjitc.utils.HibernateUtils;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
/**
* Hibernate Query的使用
* @version 1.0
* @autho ban
* @date 2019/4/8 9:09
*/
public class HibernateDemo {
public static void main(String[] args) {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
//简单查询
//String hql = "from Customer";
//条件查询
//String hql = "from Customer where cust_name like ?";
//分页查询
String hql = "from Customer";
Query query = session.createQuery("wangwu");
//设置条件
//query.setParameter(0,"wang%");
//设置分页
query.setFirstResult(3);
query.setMaxResults(3);
transaction.commit();
session.close();
}
}
Criteria
Criteria:QBC(Query By Criteria)
更加面向对象的一种查询方式
import net.zjitc.domain.Customer;
import net.zjitc.utils.HibernateUtils;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction;
import java.util.List;
/**
* Hibernate Criteria的使用
* @version 1.0
* @autho ban
* @date 2019/4/8 9:09
*/
public class HibernateDemo {
public static void main(String[] args) {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
//通过session获取Criteria对象
Criteria criteria = session.createCriteria(Customer.class);
/*条件查询
criteria.add(Restrictions.like("cust_name","wang%"));
*/
criteria.setFirstResult(3);
criteria.setMaxResults(3);
List<Customer> list = criteria.list();
for (Customer customer : list){
System.out.println(customer);
}
transaction.commit();
session.close();
}
}
SQLQuery
SQLQuery用于接收SQL。