【SSH快速进阶】——探索Hibernate对象的三种状态:Transient、Persistent、Detached
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/details/48850401
学习过操作系统的朋友,脑子里肯定都会有这张进程的状态转换图:
当所有条件就绪,进程被调度执行,时间片到的时候,进程被挂起,进入就绪状态……对进程进行的不同操作会导致进程进入到不同的状态。
Hibernate中对象的有三种状态:临时状态(Transient)、持久化状态(Persistent)、游离状态(Detached),这三种状态也随着对其执行不同的操作互相转换。
先看一张图来宏观了解一下这三种状态:
下面分别对这三种状态进行说明(为了简洁直观,本文所有代码均没有加异常处理)
1、临时状态(Transient):
简单来说,处于Transient的对象,就是我们刚new出来、尚未被session管理的对象。它与数据库没有任何交集(数据库中没有与之对应的数据),可以被看做是携带信息的载体,可以对对象本身的属性、方法进行操作。
比如:
User user=new User();
user.setName="Danny";
user.setPassword="123456";
这时的user就是处于Transient状态的对象。
2、 持久化状态(Persistent):
Persistent的对象,已经被加入到session缓存中(被session管理)。对持久化状态的对象进行的操作,只是暂时在缓存内部的变化,在commit之前,并没有提交到数据库,但在数据库中存在与之对应的数据(这句话可能会有些朋友会不太明白,下面会稍作解释)。
//读取配置文件
Configuration cfg=new Configuration().configure();
//建立SessionFactory
factory=cfg.buildSessionFactory();
//获取session
Session session = factory.openSession();
//事务开启
Transaction tx = session.beginTransaction();
//Transient状态
User user = new User();
user.setName("Danny");
user.setPassword("123456");
// Persistent状态
session.save(user);
user.setName("DannyHoo");
tx.commit();
session.close;
如上,当session对user执行了save/saveOrUpdate方法后,user对象状态由Transient转化为Persistent,这时我们对其操作,都会记录在session的缓存中。
比如上面的例子,先对user执行了setName(“Danny”)的操作,然后进行save操作,在事务提交之前,又对user执行了setName(“DannyHoo”)的操作。对user执行的save操作就相当于向数据库执行了插入操作,随后对user执行的setName(“DannyHoo”)相当于执行了一次更新操作,当事务提交,对缓存进行清理(脏数据检查)的时候,会和数据库同步,执行两条sql语句。
Hibernate: insert into User (name, password, id) values (?, ?, ?)
Hibernate: update User set name=?, password=? where id=?
在session.save()之后和session.close之前,user一直处于Persistent状态。
然后再通过上面的例子解释一下“在数据库中存在与之对应的数据”这句话,在例子中,User类的主键生成策略为uuid,我并没有在代码中为user设置id,在save(user)之前,user的id为null,save之后,user的id已经生成: save之前:
save之后:
这时,在session的缓存中已经有一份与数据库中相对应的一条数据了(可以说user已经在真正意义上成为数据库中的一条记录了),只不过没提交事务之前还没更新到数据库中,一旦提交事务,便会将这条记录“copy”到数据库中。
3、游离状态(Detached):
游离状态的对象,不受session管理,而且在数据库中存在与之对应的数据。根据上文可知当session执行close(关闭)、clear(清除缓存)之后,被session管理的对象的状态就由Persistent转化为Detached;当session执行了evict (逐出)之后,被逐出的对象的状态就由Persistent转化为Detached。
//读取配置文件
Configuration cfg=new Configuration().configure();
//建立SessionFactory
factory=cfg.buildSessionFactory();
//获取session
Session session = factory.openSession();
//开启事务
Transaction tx = session.beginTransaction();
//Transient状态
User user = new User();
user.setName("Danny");
user.setPassword("123456");
// Persistent状态
session.save(user);
user.setName("DannyHoo");
//提交事务,session关闭
tx.commit();
session.close;
//Detached状态
user.setName("胡玉洋");
//重新开启session
Session session = factory.openSession();
//重新开启事务
tx = session.beginTransaction();
//再次将user纳入session管理,save之后user又将编程Persistent状态,最后在session检查脏数据时会将数据库同步到与session缓存中的数据一致
session.update(user);
//提交事务,session关闭
tx.commit();
session.close;
上述代码中,在session第一次关闭之后,user的状态就由Persistent转化为Detached,它跟数据库中的数据一致,可以看做是已经真正更新到数据库中的状态。
Hibernate中常用方法
最后简单介绍一下session中的几个常用方法,来帮助理解Hibernate对象的这三种状态。 ● get():根据id查询记录,如果查询结果为空,返回null; ● load():根据id查询记录,如果查询结果为空,抛出ObjectNotFoundException,并且load支持懒加载,通过get和load查询出的记录会立刻进入Persistent状态; ● save:save方法将对象保存到数据库,但并没有立即执行插入语句,只是将对象加入到session缓存中,根据主键生成策略生成主键(即时对象中已经有id也会重新生成一份),生成insert语句; ● saveOrUpdate:判断数据库中是否存在与之对应的数据,如果存在,只更新,否则插入,通过save和saveOrUpdate方法,对象会立即进入Persistent状态; ● evict:evict方法将指定对象从session缓存中逐出,使其进入Detached状态; ● close:close关闭session; ● clear:清除session中所有缓存; ● update:当对一个Detached状态的对象更新(update)的时候,会使其进入持久化状态。 ● delete:当对一个Persistent或Detached状态的对象删除的时候,会使其进入Transient状态。
【 转载请注明出处——胡玉洋《【SSH快速进阶】——Hibernate对象的三种状态:Transient、Persistent、Detached】
- Ubuntu 17.04 x64 安装 Docker CE
- 这是一篇清晰易懂的 Rxjava 入门教程
- 可能是最详细的部署:Docker Registry企业级私有镜像仓库Harbor管理WEB UI
- 简单好用的阴影库 ShadowLayout
- 【项目管理和构建】——Maven下载、安装和配置(二)
- 打印机安全研究(一):不容乐观的网络打印机安全状况
- Apache Maven 入门篇
- hyperledger v1.0.5 区块链运维入门(一)
- 分析无线遥控器信号并制作Hack硬件进行攻击
- 第二章:Shiro入门——深入浅出学Shiro细粒度权限开发框架
- 在Apache Spark上跑Logistic Regression算法
- 第四章:Shiro的身份认证(Authentication)——深入浅出学Shiro细粒度权限开发框架
- 第五章:Shiro的授权(Authorization)——深入浅出学Shiro细粒度权限开发框架
- 第六章:Shiro的Realms——深入浅出学Shiro细粒度权限开发框架
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- [算法] 数组排序 - 冒泡排序法与直接选择排序法
- TS 设计模式01 - 工厂模式
- Spring与Mybatis的整合
- Python中的计数 - Counter类
- vue 记账本
- c/c++补完计划(三): 素数统计
- Python正则表达式(上)
- 附001.Nginx location语法规则
- 016.Nginx HTTPS
- 架构师写的BUG,非比寻常
- Python爬虫获取豆瓣TOP250电影详情
- docker容器常用命令
- MapReduce之自定义分区器Partitioner
- MySQL ORDER BY,GROUPBY 与各种JOIN
- (三) Mybatis动态SQL语句 - Titan的Mybatis系列学习笔记