【Hibernate步步为营】--核心对象+持久对象全析(二)

时间:2023-02-21 19:28:54

上篇文章讨论了Hibernate的核心对象,在开发过程中经经常使用到的有JTA、SessionFactory、Session、JDBC,当中SessionFactory可以看做数据库的镜像,使用它可以创建Session对象。JTA用来管理事务,在对象模型改动后同步到数据库中。另外还有Hibernate作为持久层它封装了持久层的转化过程。以下着重讨论持久对象的转换过程。

一、状态解析


      Hibernate的持久对象主要分为三个状态,Transient、Persistent、Detached。当中Transient称为瞬态,没有被数据库管理,Hibernate没有为对象分配id,在数据库中没有相应的行,一般在new出一个对象后转化为瞬态;Persistent称为持久化。此时已经被Session管理。Hibernate为对象分配了一个id(该id能够使用其他方法手动或者自己主动分配,id的类型能够在User.hbm.xml中配置),在数据库中已经有了相应的一行,在调用session的save方法后会提交到数据库中。Detached称为脱管对象。此时已经将改动同步到了数据库中,它有Hibernate分配的id,可是此时的id是在持久化状态分配的,在编程时此状态的对象往往已经不受session管理。假设想要再次改动能够再次创建一个session,然后管理对象。Transient、Detached的对象假设长时间不使用的话。会在某一时间段被Java的垃圾回收装置进行回收。
【Hibernate步步为营】--核心对象+持久对象全析(二)

1、Transient:数据库中没有,没有被Session管理



       从Hibernate的体系结构图中不难看出。对象的瞬态是在应用程序中完毕的,当对象被创建后即转变为瞬态,它还没有持久化的过程。也就是说并没有持久化标示(id号。Hibernate在创建持久化对象时都会为该对象指定一个id标示。保证唯一性)。

瞬态的对象假设没有不论什么的操作的话。会在某一时刻消亡,并被Java的垃圾回收器回收。

事例演示:在SessionTest中加入一个名为testSave1的方法,代码例如以下:

public void testSave1(){
Session session=null;
Transaction tx = null;
try{
session=HibernateUtils.getSession();
//开启事务
tx= session.beginTransaction(); //Transient状态
User user=new User();
user.setName("zhangsi");
user.setPassword("123");
user.setCreateTime(new Date());
user.setExpireTime(new Date()); }catch(Exception e){
e.printStackTrace();
if(tx != null){
tx.rollback();
}
}finally{
HibernateUtils.closeSession(session);
} //detached状态
}

在save方法处设置断点,执行调试。输出结果例如以下图:

【Hibernate步步为营】--核心对象+持久对象全析(二)
   

2、Persistent:数据库中有,被session管理



        一个瞬态的对象操作完毕后须要保存操作,这时候调用save或者其它保存方法时即被转换为持久对象,这时候Hibernate给该对象创建一个持久化标示,并且可能在数据库中有了一个相应行,并且该标示与Java标示(该值表示对象在内存的位置)等价。
       另外一个没有被创建的对象相同能够使用其他的方法来直接转换到该状态,如上图的get、load等方法。

persistent状态的对象若发生了改变。则在清理内存时或者在脏数据检查时会把改变同步到数据库中。那么此时会生成两条语句,分别为insert和update。

在SessionTest中加入saveTest2方法。測试持久态

public void testSave2(){
Session session=null;
Transaction tx = null;
try{
session=HibernateUtils.getSession();
//开启事务
tx= session.beginTransaction(); //Transient状态
User user=new User();
user.setName("zhangsi");
user.setPassword("123");
user.setCreateTime(new Date());
user.setExpireTime(new Date()); //persistent状态
//persistent状态的对象,当对象的属性发生改变的时候
//Hibernate在清理缓存(脏数据检查)的时候,会和数据库同步
session.save(user);
user.setName("lisi"); //能够显示的调用udpdate方法,由于此时为持久状态。调用udpate没有什么意义
session.update(user); tx.commit(); }catch(Exception e){
e.printStackTrace();
if(tx != null){
tx.rollback();
}
}finally{
HibernateUtils.closeSession(session);
}
}

调用save方法后进入的持久态。此时的为user对象加入了id标识:

【Hibernate步步为营】--核心对象+持久对象全析(二)

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhhbmdfeGlueGl1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

        方法运行完毕后会向数据库中加入新的一条信息,细心的童鞋能够看出方法中调用了两次setName方法。最后结果是什么呢。查看mysql中的表能够看到:
【Hibernate步步为营】--核心对象+持久对象全析(二)

数据库中加入的最后信息是lisi,所以它最后运行了更新操作,此时在控制台中会打印两条sql语句,分别为insert和update语句。

Note:在提交事务或者关闭Session前。会调用Session的flush方法对每一个更改进行操作。

3、Detached:数据库中有。没有被session管理



       脱管状态下的对象事实上已经被映射到了数据库中。仅仅只是此时还没有被垃圾回收期回收。此时的对象拥有持久化标识。该标识相应着数据库中的一行,可是不保证该标识与Java标识相应。

       在SessionTest类中加入testSave3方法。測试Detached状态下对象和数据库,代码例如以下:


public void testSave3(){
Session session=null;
Transaction tx = null;
User user=null;
try{
session=HibernateUtils.getSession();
//开启事务
tx= session.beginTransaction(); //Transient状态
user=new User();
user.setName("zhangsi");
user.setPassword("123");
user.setCreateTime(new Date());
user.setExpireTime(new Date()); //persistent状态
//persistent状态的对象。当对象的属性发生改变的时候
//Hibernate在清理缓存(脏数据检查)的时候,会和数据库同步
session.save(user);
user.setName("lisi"); tx.commit(); }catch(Exception e){
e.printStackTrace();
if(tx != null){
tx.rollback();
}
}finally{
HibernateUtils.closeSession(session);
} //detached状态
user.setName("wangwu");
try{
session=HibernateUtils.getSession();
session.beginTransaction(); //将detached状态的对象又一次纳入session管理
//此时将变为persistent状态的对象
//persistent状态的对象,在清理缓存时会和数据库同步
session.update(user);
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
} }

运行完毕后,查看数据库中信息,例如以下图:

【Hibernate步步为营】--核心对象+持久对象全析(二)

分析运行结果,不难发现它最后完毕的是更新操作,不同的是detached状态下的对象必须又一次定义新的Session对象,由于Session对象线程不安全。easy出错。

结语


       上文主要讨论分析了Hibernate持久对象在整个声明周期的状态转化过程,这几种状态的相互转化使得关系模型和对象模型进行了紧密的关联,另外在使用配置文件来管理这几种状态,这样使得Hibernate的操作简单。而且功能强大。上文仅仅是针对持久对象的几种状态做了初步的解析。另外还有状态之间的转化方法将会在下篇文章讨论。

【Hibernate步步为营】--核心对象+持久对象全析(二)的更多相关文章

  1. 【Hibernate步步为营】--核心对象+持久对象全析(一)

    引言         上篇博客对Hibernate进行了基本的解析.并分析了它的一些特性. Hibernate可以如此的流行也是由于它有诸多长处,不论什么事物都有两面性.Hibernate尽管流行.可 ...

  2. 【Hibernate步步为营】--核心对象+持久对象全析(三)

    上篇文章讨论了Hibernate持久对象的生命周期,在整个生命周期中一个对象会经历三个状态,三种状态的转换过程在开发过程中是可控的.并且是通过用法来控制它们的转化过程.详细的转化过程今天就来着重讨论下 ...

  3. Hibernate的核心对象关系映射

    Hibernate的核心就是对象关系映射: 加载映射文件的两种方式: 第一种:<mapping resource="com/bie/lesson02/crud/po/employee. ...

  4. hibernate在持久对象的生命周期(三州:*状态,持久状态,*状态 之间的转换)

    三种状态的基本概念: 1.  临时身份(Transient):也被称为*状态,它只存在于内存中,并且在数据库中没有相应的数据. 使用new创建的对象,久化,没有处于Session中,处于此状态的对象 ...

  5. Hibernate入门(3)- 持久对象的生命周期介绍

    在hibernate中对象有三种状态:瞬时态(Transient). 持久态(Persistent).脱管态或游离态(Detached).处于持久态的对象也称为PO(Persistence Objec ...

  6. Hibernate(开放源代码的对象关系映射框架)

    Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自 ...

  7. JavaEE之Hibernate(开放源代码的对象关系映射框架)

    Hibernate(开放源代码的对象关系映射框架) 1.简介 Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全 ...

  8. Hibernate一级缓存Session和对象的状态

    建议看原文:https://blog.csdn.net/qq_42402854/article/details/81461496 一.session简介        首先,SessionFactor ...

  9. Hibernate的session缓存和对象的四种状态

    一.session缓存 说session缓存就得说到JAVA对象的生命周期,当没有任何引用指向一个对象时,对象则可以被gc回收,也就是生命周期结束了 而hibernate获取一个对象后,会将对象存入s ...

随机推荐

  1. jQuery ui 框架

    jQuery ui框架很多,除了官方提供的jquery UI(如果你还不知道什么是jQuery UI,请看下载了jquery ui后如何使用),还有很多第三方提供的ui框架,因官方提供的jquery ...

  2. Reporting Service 没有权限登陆

    在配置好Reporting Service之后,登陆Report Mananger( http://localhost/Reports/Pages/Folder.aspx)出现一个异常,本地用户没有权 ...

  3. IO负载高的来源定位

    前言: 在一般运维工作中经常会遇到这么一个场景,服务器的IO负载很高(iostat中的util),但是无法快速的定位到IO负载的来源进程和来源文件导致无法进行相应的策略来解决问题. 这个现象在MySQ ...

  4. &lbrack;04&rsqb; SQL语句优化之索引

    1.索引的概念 根据书的目录可以知道内容所在的页码,不用一页一页翻书,可直接通过页码找到内容.数据库的索引类似于书本的目录,索引指向内容存储位置,可直接定位到内容而不必扫描整张表,减少了磁盘的I/O次 ...

  5. REST响应处理

    JAX-RS 2.0 支持4种返回值类型的响应,分别是无返回值.返回Response类实例.返回GenericEntity类实例和返回自定义类实例. 1.在返回值类型是VOID的响应中,其响应实体为空 ...

  6. &lbrack;置顶&rsqb; JQuery插件学习教程

    这是JQuery其它常用插件的视频教程,包括validate插件,.comet插件等.同时有大量实例项目,如果你是喜欢JQuery的童鞋千万不要错过. 教程的内容有: 1_validate插件(1) ...

  7. Android&lowbar;硬编码设置TextView字体大小

    使用如下代码时,发现字号不会变大,反而会变小:size = (int) mText.getTextSize() + 1;mText.setTextSize(size);后来发现getTextSize返 ...

  8. C&plus;&plus;中输出流的刷新问题和 endl和 &bsol;n的区别

    <C++ Primer>第5版 P6中提到endl具有换行和刷新输出流两个作用,那么没有 endl是否还会将输出流中的内容输出到设备中,再刷新输出流呢? cout << &qu ...

  9. 我的 FPGA 学习历程(08)—— 实验:点亮单个数码管

    数码管是一种常见的用于显示的电子器件,根据数码管大致可以分为共阴极和共阳极两种,下图所示的是一个共阳极的数码管的电路图(摘自金沙滩工作室的 51 开发板电路图),我的 AX301 开发板与这张图的情况 ...

  10. 使用php的curl爬去青果教务系统 课表&lpar;转&rpar;

    1. 分析 首先我们要了解 Http Cookie 的作用(可参考HTTP cookies 详解),简单来说就是维持一个会话,这样我们就能在登陆一个网页后,就能进入这个网页需要登陆的界面. 现在我们需 ...