目录
学习笔记,为了加强记忆和深入理解在此记录备忘。如有错误和理解不当之处,还望指正。万分感谢!
另外,实例和内容有些是参照网络其他博文,如有侵权可联系删除。
学习重点:
1、区分Java对象内存地址的引用和OID引用;
2、注意几种状态的转换,避免OID引用冲突;
一、映射对象标识符(OID)
1.1 概述
1) Java语言按内存地址识别或区分同一个类的不同对象。
2) 关系数据库使用主键来识别或区分同一张表中的不同记录。
3) Hibernate使用OID来建立内存对象与关系数据库表中记录的对应关系
由上图可以看出OID和数据库主键是一一对应的,而且不同的对象可以指向同一个OID。也就是说当一个对象获取一个OID后,再有其他对象请求到同一个条数据的时候,直接使用session中的OID,不必再次查询数据库。
确保OID的唯一性和久性,开发人员不应该让java应用程序来设定OID(很容易出现几个相同的OID),应该让数据库或者hibernate来管理这些OID
1.2 主键分类
业务主键:和业务相关的主键(例如:身份证号),业务相关没有变动唯一的可以使用业务主键
代理主键:没有业务意义(例如:自增),只是作为唯一标识(用的稍微多点)
1.3 常用的OID生成器
OID生成器 | 适用对象 | 描述 | 支持的数据库 |
increment | 代理主键 | 由hibernate自动一递升的方式生成标识符,每次增量为1 | |
indentify | 代理主键 | 由数据库底层生成标识符,前提是底层数据库支持自动增长字段类型 | DB2、Mysql、MS SQL Service、Sybase、HypersonicSQL |
sequence | 代理主键 | hibernate根据底层数据库的序列来生成标识符 前提是底层数据库支持序列 | DB2、PostgreSQL、Oracle、 SAP DB |
hilo | 代理主键 | hibernate根据high/low算法来生成标识符,hibernate把特定表的字段作为"hight"的部分,默认情况下选用hibernate_unique_key表的next_hi字段 | |
native | 代理主键 | 根据底层数据库对自动生成标识符的支持能力,来选择identity、sequence、hilo中的一种 | |
uuid.hex | 业务主键 | hibernate采用128位的UUID(Universal Unique Identification)算法来生成标识符,UUID能够在网络环境生成唯一的字符串标志符(估计跟MAC有关),不常用,占用空间多 | |
assigned | 业务主键 | 由java应用程序负责生成标识符,为了能让java应用程序设置OID,不能把setId()方法声明为private类型,应该尽量避免使用自然主键 | |
foreign | 一对一关联 | 用另一个关联的对象的标识符作为当期的标识符 |
1.4 几种数据库支持的生成器
Ø MySQL: identity、increment、hilo、native
Ø MS SQL Server:identity、increment、hilo、native
Ø Oracle:sequence、seqhilo、hilo、increment、native
Ø 跨平台开发:native
以上内容参照https://blog.youkuaiyun.com/jazywoo123/article/details/7837966的博客。
二、持久化对象状态
2.1 几种状态
-
临时状态:新创建的对象,还没有持久化,OID是null、数据库中没有记录而且不在session缓存中。
-
例如:Student student = new Student();
-
-
持久化状态:已经被持久化,并且在session缓存中,数据库表中的每条记录之对应唯一持久化对象。
-
例如:session.save(Obj); 保存完了后,并且没有session.close();
-
-
删除状态:从数据库中删除,并且不在session缓存中。但是对象还在内存中,可以引用。
-
例如:session.delete(Obj); 并且session.close(); 一般情况下,应用程序不该再使用被删除的对象
-
-
游离状态:持久化后关闭session。对象处于游离状态,对象仍然在内存中,可以引用
-
例如:session.save(Obj); 保存完了后,并且session.close();
-
2.2 常用的session方法
- save:持久化临时对象,提交事物写数据库。如果没有写提交事物,关闭session时自动写数据库。
- load和get:根据OID加载数据库中的对象
- 区别: 如果数据库没有OID记录,load抛出异常,get返回null;
load默认延时加载(调用的时候加载),get默认立即检索
所以,删除时用load,修改时用get。
- 区别: 如果数据库没有OID记录,load抛出异常,get返回null;
- update:可以将游离对象转化为持久化对象
- saveOrUpdate:传入的是临时对象时调用save;传入的是游离对象时调用update
- merge:一个游离状态的OID和临时状态的OID一样,update游离对象时会出错,merge可以避免这个
- 例如:一个Student对象OID是1,已经持久化和关闭session,对象处于游离状态。
Student student1 = new Student();创建一个临时对象,
新建会话加载了一个OID是1 的对象。这时候去update游离对象就会报错。
Student student2 = session1.get(Student.class, Long.valueOf(1));
update和merge可以优先考虑merge。
- 例如:一个Student对象OID是1,已经持久化和关闭session,对象处于游离状态。
- delete:删除数据库的数据