目录
0. 结构图1. 持久化类的编写规则
1.1 持久化和持久化类1.2 持久化类的编写规则2. 主键生成策略
2.1 主键的分类2.2 主键生成策略3. 持久化类的三种状态【了解】
3.1 持久化类的三种状态3.2区分三种持久化状态3.3 持久化的三种状态的转换
3.3.1 持久态的三种状态转换图3.3.2 瞬时态对象3.3.3 持久态3.3.4 托管态对象3.3.5 持久态对象的特性4. Hibernate的一级缓存
4.1 缓存概述4.2 hibernate的缓存4.3 证明一级缓存的存在4.4 一级缓存的结构5. Hibernate事务管理
5.1 什么是事务5.2 事务的特性5.3 不考虑隔离性,引发安全问题5.4 读问题的解决5.5 设置事务的隔离级别5.6 Hibernate解决Service事务管理6. HIbernate的其他API
6.1 Query6.2 Criteria6.3 SQLQuery【了解】
0. 结构图
1. 持久化类的编写规则
1.1 持久化和持久化类
持久化:将内存中的一个对象持久化到数据库的过程,Hibernate框架就是用来进行持久化的框架。持久化类:一个Java对象与数据库的表建立了映射关系,那么这个类在Hibernate中称为持久化类。
持久化 = Java类 + 映射文件
1.2 持久化类的编写规则
对持久化提供一个无参的构造方法:HIbernate底层需要使用反射生成实例。属性需要私有化,对私有属性提供public 的get和set方法:Hibernate中获取,设置对象的值。对持久化提供一个唯一标识OID与数据库主键对应:Java中通过对象的地址区分是否是同一个对象,数据库中通过主键确定是否是同一个记录,在Hibernate中通过持久化类的OID的属性区分是否是同一个对象。持久化类中属性尽量使用包装类型:因为基本数据类型的默认值是0,那么0就会有很多歧义。包装类型默认值是null。持久化类不要使用final进行修饰:延迟就在本身是Hibernate一个优化手段。返回的是一个代理对象,可以对没有实现接口的类产生代理,这种代理使用了非常底层的字节码增强技术,继承这个类进行代理。如果不能被继承,不能产生代理对象,延迟就在也就失效了。load和get方法就一致了
2. 主键生成策略
2.1 主键的分类
自然主键:
主键的本身就是表中的一个字段(实体中的一个具体的属性)。创建一个人员表,人员都会有一个身份证号(唯一不可重复的),使用了身份证号作为主键,这种主键称为是自然主键。代理主键:
主键的本身不是表中必须的一个字段(不是实体中的某个具体的属性)创建一个人员表,没有使用人员中的身份证号,用来一个与这个表不相关的字段ID。这种主键称为代理主键。在实际开发中,尽量使用代理主键
一旦自然主键参与到业务逻辑中,后期有可能需要修改源代码好的程序设计满足OCP原则,对程序的扩展时open的,对修改原阿门时close的。
2.2 主键生成策略
在实际开发中一般不允许用户手动设置主键,一般将主键交给数据库,手动编写程序进行设置。在Hibernate中为了减少程序的编写,提供了很多种的主键生成策略。increment:Hibernate中提供的自动增长机制,适用short、int、long类型的主键。在单线程程序中使用。
首先发送一条Sql语句: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:外部的。一对一的一种关联映射的情况下使用。(了解)
3. 持久化类的三种状态【了解】
3.1 持久化类的三种状态
Hibernate时持久层框架,通过持久化类完成ORM操作。Hibernate为了更好的管理持久化类,将持久化类分为三种状态。持久化类 = Java类 + 映射
瞬时态:这种对象没有唯一的标识OID,没有被session管理,称为瞬时态对象。持久态:这种对象有唯一标识OID,被session管理,称为持久态对象。
持久化类的持久态的对象,可以自动更新数据库托管态:这种对象有唯一标识OID,没有被session管理,称为托管态对象。
3.2区分三种持久化状态
@Test
//三种状态的区分
public void demo1() {
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Customer customer = new Customer(); // 瞬时态对象:没有唯一标识OID,没有被session管理
customer.setCust_name("王晓东");
Serializable id = session.save(customer); // 持久态对象:有唯一标识OID,被session管理
tx.commit();
session.close();
System.out.println("客户名称: " + customer.getCust_name()); // 托管态对象:有唯一标识OID,没有被session管理
}
3.3 持久化的三种状态的转换
3.3.1 持久态的三种状态转换图
3.3.2 瞬时态对象
获得:
Customer customer = new Customer();状态转换
瞬时---->持久
save(Obejct obj)、saveOrUpdate(Object obj);瞬时----->托管
customer.setCust_id(1);
3.3.3 持久态
获得
get()、load()、find()、iterate()Customer customer = session.get(Customer.class,1L);状态转换
持久----->瞬时
delete()持久----->托管
close()、clear()、evict(Object obj)
3.3.4 托管态对象
获得
Customer customer = new Customer();customer.setCust_id(1L);状态转换
托管---->持久
update()、 saveOrUpdate()托管----->瞬时
customer.setCust_id(null)
3.3.5 持久态对象的特性
@Test // 持久态对象自动更新数据库
public void demo2() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
// 获得持久态对象:
Customer customer = session.get(Customer.class, 1L);
customer.setCust_name("王喇嘛");
//session.update(customer);
// 不写这句话也可以将数据保存到数据库,这是持久态对象的特征,底层是一级缓存
transaction.commit();
session.close();
}
4. Hibernate的一级缓存
4.1 缓存概述
什么是缓存:
缓存时一种优化的方式,将数据存储到内存中,使用的时候直接从缓存中获取,不用通过存储源。
4.2 hibernate的缓存
Hibernate框架中提供了很多优化手段,比如缓存、抓取策略。Hibernate中提供了两种缓存机制,一级缓存和二级缓存。Hibernate的一级缓存就是指Session缓存,Session缓存是一块内存空间,用来存放互相管理的Java对象,在使用Hibernate查询对象的时候,首先会使用对象属性的OID值在Hibernate的一级缓存中进行查找,如果找到匹配的OID值得对象,就直接将该对象从一级缓存中取出使用,不会再查询数据库;如果没有找到相同得OID值得对象,则会去数据库中查找相应得数据。当从数据中查询到到所需数据时,该数据信息也会放置到一级缓存中。Hibernate得一级缓存的作用就是减少对数据库的访问次数。再在Session接口的实现中包含了一系列的Java集合,这些Java集合构成了Session缓存。只要Session实例没有结束生命周期,存放在它缓存中的对象也不会结束生命周期。所以一级缓存也被称为是Session基本的缓存。Hibernate的二级缓存是SessionFactory级别的缓存,需要配置的缓存。二级缓存已经被Redis取代,实际开发过程不会使用。一级缓存是自带的不可卸载的。
4.3 证明一级缓存的存在
package com.itzhouq.hibernate.demo1;
import java.io.Serializable;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import com.itzhouq.hibernate.utils.HibernateUtils;
public class Demo3 {
// 证明一级缓存的存在
@Test
public void test() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
// Customer customer1 = session.get(Customer.class, 1L); // 发送SQL语句
// System.out.println(customer1);
//
// Customer customer2 = session.get(Customer.class, 1L); // 不发送SQL语句
// System.out.println(customer2);
Customer customer = new Customer();
customer.setCust_name("凤姐");
Serializable id = session.save(customer);
Customer customer2 = session.get(Customer.class, id); // 不发送SQL语句
System.out.println(customer2);
transaction.commit();
session.close();
}
}
4.4 一级缓存的结构
一级缓存中的特殊区域:快照区
5. Hibernate事务管理
5.1 什么是事务
事务:事务是指逻辑上的一组操作,这组操作的各个逻辑单元要么全部成功,要么全都失败。
5.2 事务的特性
原子性:代表事务不可分割。一致性:代表事务执行的前后,数据的完整性保持一致。隔离性:代表一个事务的执行过程中,不应该受到其他事务的干扰。持久性:代表事务执行完成后,数据就持久化到数据库中。
5.3 不考虑隔离性,引发安全问题
读问题:
脏读:一个事务读取到另一个事务未提交的数据。不可重复读:一个事务读取到另一个事务已经提交的update数据,导致在前一个事务多次查询结果不一致。虚读:一个事务读取到另一个事务已经提交的insert数据,导致在前一个事务多次查询结果不一致。写问题【了解】
引发两类丢失更新
5.4 读问题的解决
设置事务的隔离级别
Read uncommitted:以上读问题都会发生Read committed:解决脏读,但是不可重复读和虚读有可能发生(Oracle)Repeatable read:解决脏读和不可重复读,但是虚读有可能发生(Mysql)Serlializable:解决所有读问题
5.5 设置事务的隔离级别
在主配置文件中添加以下配置
<!-- 设置事务的隔离级别 -->
<property name="hibernate.connection.isolation">4</property>
4为MySQL数据库的默认级别
数字和隔离级别的对应关系
1----------Read uncommitted isolation2----------Read committed isolation4----------Repeatable read isolation8----------Serializable isolation
5.6 Hibernate解决Service事务管理
Service层的事务
代码和配置
改写工具类,添加getCurrentSession()订单
package com.itzhouq.hibernate.utils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/*
* Hibernate的工具类
*/
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();
}
}
在主配置文件中配置当前线程绑定的Session
<!-- 配置当前线程绑定的Session -->
<property name="hibernate.current_session_context_class">thread</property>
测试
package com.itzhouq.hibernate.demo1;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import com.itzhouq.hibernate.utils.HibernateUtils;
/*
* 测试当前线程绑定的Session
*/
public class Demo4 {
@Test
public void test() {
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
Customer customer = new Customer();
customer.setCust_name("王希");
session.save(customer);
transaction.commit();
//session.close();//不需要关闭
}
}
注意:绑定线程的session不需要手动关闭。因为当前线程自动获得与当前线程绑定的Session,线程结束之后,自动关闭Sesson,不需要手动关闭。
6. HIbernate的其他API
6.1 Query
Query接口使用接收HQL,查询多个对象
HQL:Hibernate Query Language:HIbernate查询语言,这种语言与SQL的语法及其类似,面向对象的查询语言。代码package com.itzhouq.hibernate.demo1;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import com.itzhouq.hibernate.utils.HibernateUtils;
/*
* HIbernate的其他API
*/
public class Demo5 {
@Test // Query
public void test() {
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
// 通过Session获得Query接口
//简单查询
//String hql = "from Customer";
//条件查询
//String hql = "from Customer wehre cust_name like ?";
//分页查询
String hql = "from Customer";
Query query = session.createQuery(hql);
//设置条件
//query.setParameter(0, "王%");
//设置分页
query.setFirstResult(0);
query.setMaxResults(3);
List<Customer> list = query.list();
for (Customer customer : list) {
System.out.println(customer);
}
transaction.commit();
}
}
6.2 Criteria
条件查询:Query By Criteria
更加面向对象的一种查询方式
代码
@Test // Criteria
public void test2() {
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
//通过Session获得Criteria对象
Criteria criteria = session.createCriteria(Customer.class);
//List<Customer> list = criteria.list();
//条件查询
// Criteria add = criteria.add(Restrictions.like("cust_name", "王%"));
// List<Customer> list = criteria.list();
//分页查询
criteria.setFirstResult(0);
criteria.setMaxResults(2);
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer);
}
transaction.commit();
}
6.3 SQLQuery【了解】
SQLQuery用于接收SQL。特别复杂情况下使用SQL。
转载于:https://www.cnblogs.com/itzhouq/p/hibernate02.html