Hibernate框架笔记02_主键生成策略_一级缓存_事务管理
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
作为下一条的记录的主键
- 首先发送一条Sql语句:
- 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 isolation
- 2----------
Read committed isolation
- 4----------
Repeatable read isolation
- 8----------
Serializable isolation
- 1----------
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();
}
}
- HQL:
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。
Hibernate框架笔记02_主键生成策略_一级缓存_事务管理的更多相关文章
- hibernate框架学习之主键生成策略generator
1)手工控制 assigned(不限制类型) 2)数据库自动生成 uuid(字符串类型) increment(整型数值类型) identity (整型数值类型) sequence (整型数值类型) n ...
- Hibernate之:各种主键生成策略与配置详解
1.assigned 主键由外部程序负责生成,在 save() 之前必须指定一个.Hibernate不负责维护主键生成.与Hibernate和底层数据库都无关,可以跨数据库.在存储对象前,必须要使用主 ...
- java框架之Hibernate(2)-持久化类&主键生成策略&缓存&事务&查询
持久化类 概述 持久化:将内存中的对象持久化到数据库中的过程就是持久化.Hibernate 就是用来进行持久化的框架. 持久化类:一个 Java 对象与数据库的表建立了映射关系,那么这个类在 Hibe ...
- Hibernate(4)——主键生成策略、CRUD 基础API区别的总结 和 注解的使用
俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及的知识点总结如下: hibernate的主键生成策略 UUID 配置的补充:hbm2ddl.auto属性用法 注解还是配置文件 h ...
- (转) Hibernate持久化类与主键生成策略
http://blog.csdn.net/yerenyuan_pku/article/details/65462930 Hibernate持久化类 什么是持久化类呢?在Hibernate中持久化类的英 ...
- Hibernate的几种主键生成策略
主键类型: 业务主键(natural key):业务主键的值是来源于一个业务数据. 代理主键(surrogate key):代理主键需要采用一种方式来生成某个唯一值. 代理主键的生成策略: 1.hib ...
- Hibernate遇到oracle之主键生成策略
一直用Hibernate+mysql,感觉Hibernate很好用,也出过什么大问题:这周,公司的产品要部署到Orecle,虽然产品号称支持Oracle但是我自己知道,这个产品压根儿就没在Oracle ...
- hibernate(二)主键生成策略
hibernate主键生成策略主要指的是在实体类orm的配置 <id name=""> <generator class="native"&g ...
- 大家一起撸代码之——Hibernate各种主键生成策略与配置详解
1.assigned 主键由外部程序负责生成,在 save() 之前必须指定一个.Hibernate不负责维护主键生成.与Hibernate和底层数据库都无关,可以跨数据库.在存储对象前,必须要使用主 ...
随机推荐
- .NET Core 迁移躺坑记
最近将自己负责的一个核心接口系统从.Net Framework迁移到了.Net Core. 整体过程,从业务层面说一般般吧(整体还好但还是搞的业务有感,没出严重故障)但是技术层面上感觉其实并没有达到要 ...
- Servlet底层原理、Servlet实现方式、Servlet生命周期
Servlet简介 Servlet定义 Servlet是一个Java应用程序,运行在服务器端,用来处理客户端请求并作出响应的程序. Servlet的特点 (1)Servlet对像,由Servlet容器 ...
- 解决VS2019中.net core WPF 暂时无法使用 Designer 的临时方法
目录 解决 VS2019 中.net core WPF 暂时无法使用 Designer 的临时方法 安装 vs 2019 professional/enterprise版本 在vs的设置里,勾选.NE ...
- 干货|一个案例学会Spring Security 中使用 JWT
在前后端分离的项目中,登录策略也有不少,不过 JWT 算是目前比较流行的一种解决方案了,本文就和大家来分享一下如何将 Spring Security 和 JWT 结合在一起使用,进而实现前后端分离时的 ...
- Visual Studio 2019 发布活动 - 2019 年 4 月 2 日
Visual Studio 2019 发布活动 2019 年 4 月 2 日,星期二 | 上午 9:00 (PT) 围观: https://visualstudio.microsoft.com/zh- ...
- 让 .NET 更方便的导入导出 Excel
让 .Net 更方便的导入导出Excel Intro 因为前一段时间需要处理一些 excel 数据,主要是导入/导出操作,将 Excel 数据转化为对象再用程序进行处理和分析,没有找到比较满意的库,于 ...
- 如何让div中的table水平居中
<div style="text-align:center"> <table border="1" cellpadding="3&q ...
- Error:Execution failed for task ':app:processDebugManifest'.
Attribute meta-data#android.support.VERSION@value value=(26.1.0) from AndroidManifest.xml:28:13-35 i ...
- Java核心技术第八章——泛型程序设计(1)
1.泛型程序设计 泛型程序设计意味着编写的代码可以被很多不同类型的对象所重用.例如:不希望为了聚集String和Integer对象分别设计不同的类.(个人觉得此处说的聚集译为:创建一个对象,属性可以为 ...
- PHP全栈学习笔记2
php概述 什么是php,PHP语言的优势,PHP5的新特性,PHP的发展趋势,PHP的应用领域. PHP是超文本预处理器,是一种服务器端,跨平台,HTML嵌入式的脚本语言,具有c语言,Java语言, ...