【Hibernate笔记整理三】持久化类与主键生成策略

版权声明:本文为 小异常 原创文章,非商用自由转载-保持署名-注明出处,谢谢!
本文网址:https://blog.csdn.net/sun8112133/article/details/106151361







本篇博客主要讲解两个重要的知识:持久化类主键生成策略


一、持久化类

1、持久化类概述

持久化类 就是将内存中某个对象的属性保存到数据库的过程。Hibernate 框架就是用来进行持久化的框架。如果一个 Java 类与数据表建立了映射关系,那么这个类在 Hibernate 中称为是 持久化类

持久化类 = Java类 + 映射文件


2、编写规则

编写一个 持久化类 需要遵循以下五个规则:

1)无参构造器

持久化类 提供一个无参数的构造方法,因为 Hibernate 底层需要使用反射机制来创建实例。


2)私有属性

属性需要私有化。对私有属性要提供 public 修饰的 get()set() 方法,因为 Hibernate 要通过 get()set() 方法来获取和设置对象的值。


3)OID 属性

持久化类 提供一个 OID 属性(对象唯一标识的属性)与数据库的主键对应。

比如我们之前在 Java 中通过对象的地址值来区分是否是同一个对象,在数据库中通过主键来确定是否是同一个记录,然而在 Hibernate 中是通过持久化类的 OID 的属性来区分是否是同一个对象。


4)类型使用包装类

持久化类 中属性尽量使用包装类型,因为有的基本数据类型的默认值是 0,那么 0 就会有很多的歧义。而包装类型默认值是 null,它代表空,没有任何歧义。


5)持久化类不要使用 final 修饰

持久化类 不要使用 final 修饰,因为 Hibernate 后期可能会使用延迟加载对该类采取一系列的优化手段(延迟加载这个概念后续博客会有专门讲解,简单的说延迟加载是通过代理模式实现的)。它最终会返回一个代理对象,如果这个类不能被继承,那么就不能产生代理对象,延迟加载就会失效。


3、三种状态

Hibernate 是持久层框架,通过 持久化类 完成 ORM (对象关系映射)操作。Hibernate 为了更好的管理 持久化类,将 持久化类 分成了三种状态:

1)瞬时态(transient)

这种对象没有唯一的标识 OID,没有被 session 管理,称为是 瞬时态对象


2)持久态(persistent)

这种对象有唯一标识 OID,被 session 管理,称为是 持久态对象持久化类持久态对象,可以自动更新数据库哦。


3)脱管态(detached)

这种对象有唯一标识 OID,没有被 session 管理,称为 脱管态对象


4)测试三种状态

@Test
public void demo1() {
	Session session = HibernateUtils.openSession();
	Transaction tx = session.beginTransaction();
	
	Customer c = new Customer();    // 瞬时态对象:没有唯一标识OID,没有被session管理
	c.setCust_name("赵六");
	session.save(c);    // 持久化对象:有唯一标识OID,被session管理
	// 这个时候可以对持久化对象进行操作
	
	tx.commit();
	session.close();
	
	System.out.println(c.getCust_name());    // 脱管态对象:有唯一标识OID,没有被session管理,因为session已经被关闭了
}

4、状态转换

1)瞬时态对象

  • 获得

    • Customer customer = new Customer();
  • 状态转换

    1. 瞬时 --> 持久
      • save(Object obj);
      • saveOrUpdate(Object obj);
    2. 瞬时 --> 脱管
      • customer.setCust_id(1);

2)持久态对象

  • 获得
    • 可以通过 get() 、load() 、find() 、iterate() 方法
    • 如:Customer customer = session.get(Customer.class, 1L);
  • 状态转换
    1. 持久 --> 瞬时
      • delete();
    2. 持久 --> 脱管
      • close();
      • clear();
      • evict(Object obj);

3)脱管态对象

  • 获得
    • Customer customer = new Customer();
    • customer.setCust_id(1L);
  • 状态转换
    1. 脱管 --> 持久
      • update();
      • saveOrUpdate();
    2. 脱管 --> 瞬时
      • customer.setCust_id(null);

5、持久类特性

持久态对象 可以自动更新数据库,它底层的原理依赖了 Hibernate 的一级缓存(关于缓存相关知识后续博客会专门进行讲解)。

@Test
// 持久化对象自动更新数据库
public void demo2() {
	Session session = HibernateUtils.openSession();
	Transaction tx = session.beginTransaction();
	
	Customer customer = session.get(Customer.class, 1);
	customer.setCust_name("张三");   // 如果更新内容和数据库内容一致,则只查询,不更新。
	
	tx.commit();
	session.close();
}


二、主键生成策略

1、主键分类

1)自然主键

自然主键 是指主键的本身就是表中的一个字段,比如一个人员表,人员都会有一个身份证号(身份证号是唯一且不可重复的),那么可以使用身份证号作为主键,那这种主键就称为是 自然主键


2)代理主键

代理主键 是指主键的本身不是表中必须的一个字段,比如一个人员表,没有使用人员中的身份证号,而是用了一个与这个表不相关的字段ID。那么这种主键就称为是 代理主键
我们在实际开发中,尽量要使用 代理主键。因为一旦自然主键参与到业务逻辑中,那后期有可能需要修改源代码。一个好的程序设计要满足 OCP 原则,也就是对程序的扩展是 open,对修改源代码是 close。


2、Hibernate 的主键生成策略

在实际开发中一般不允许用户手动设置主键,一般将主键交给数据库管理,手动编写程序进行设置。在 Hibernate 中为了减少程序的编写,提供了很多种的 主键生成策略

1)increment

该策略采用了自然增长机制,它适用 short、int、long 类型的主键。一般要在单线程程序中使用。它首先先发送一条语句:select max(id) from 表名;,然后让 id+1 作为下一条记录的主键。


2)identity

该策略采用了数据库底层的自动增长机制(MySQL、MSSQL 适用),它适用 short、int、long 类型的主键,但是像 Oracle 这种数据库不能使用此策略,因为它没有自动增长机制。


3)sequence

该策略采用的是序列方式(Oracle支持序列),它适用 short、int、long 类型的主键,但是像 MySQL 这种数据库就不能使用此策略,因为它不支持序列。


4)uuid

该策略采用的是 Hibernate 中随机生成字符串主键的方式,它适用于字符串类型主键。


5)native

该策略是本地策略,它可以在 identity 策略sequence 策略 之间进行自动切换,这个策略很常用。


6)ssigned

该策略是让 Hibernate 主动放弃主键管理,但是需要通过手动编写程序或者用户自己设置。


7)foreign

该策略是外部的。在一对一的一种关联映射的情况下才会使用,这个策略不常用,大家了解即可。



博客中若有不恰当的地方,请您一定要告诉我。前路崎岖,望我们可以互相帮助,并肩前行!



猜你喜欢

转载自blog.csdn.net/sun8112133/article/details/106151361