【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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Linux Python 加油站

什么是爬虫?python爬虫基本知识

把互联网比喻成一个蜘蛛网,那么Spider就是在网上爬来爬去的蜘蛛。 网络蜘蛛是通过网页的链接地址来寻找网页的。

1723
来自专栏不止是前端

实用主义:前端cookie介绍及操作封装

43716
来自专栏菩提树下的杨过

scala + intellij idea 环境搭建及编译、打包

大数据生态圈中风头正旺的Spark项目完全是采用Scala语言开发的,不懂Scala的话,基本上就没法玩下去了。Scala与Java编译后的class均可以运行...

7807
来自专栏Python中文社区

Python爬虫—破解JS加密的Cookie

專 欄 ❈Jerry,Python中文社区专栏作者。 blog:https://my.oschina.net/jhao104/blog github:htt...

6248
来自专栏大内老A

[WCF安全系列]谈谈WCF的客户端认证[用户名/密码认证]

对于基于Internet的应用,基于用户名和密码的认证方式是最为常用的,而WCF为你提供了不同模式的用户名认证方式。首先还是从用户凭证的表示说起。 一、用户名/...

2269
来自专栏名山丶深处

springboot集成schedule(深度理解)

5875
来自专栏CSDN技术头条

一组 Redis 实际应用中的异常场景及其根因分析和解决方案

在上一场 Chat《基于 Redis 的分布式缓存实现方案及可靠性加固策略》中,我已经较为全面的介绍了 Redis 的原理和分布式缓存方案。如果只是从“会用”的...

3323
来自专栏北京马哥教育

Python爬虫基本知识:什么是爬虫?

豌豆贴心提醒,本文阅读时间5分钟 一、网络爬虫的定义 网络爬虫,即Web Spider,是一个很形象的名字。 把互联网比喻成一个蜘蛛网,那么Spider就是...

3436
来自专栏IT杂记

Hadoop SequenceFile BLOCK压缩类型写入数据机制

最近测试Hadoop数据一致性,发现Hadoop SequenceFile BLOCK压缩类型(io.seqfile.compression.type=BLOC...

3025
来自专栏名山丶深处

springboot集成schedule(深度理解)

2305

扫码关注云+社区

领取腾讯云代金券