首页 > 其他分享 >Hibernate三种实体状态(五)

Hibernate三种实体状态(五)

时间:2022-11-11 22:36:44浏览次数:42  
标签:Hibernate 实体 transaction 瞬时 session 三种 user 游离态 User


一.Hibernate 的三种实体状态

Hibernate有三种实体状态,有瞬时态(transiant),持久态(persistent),游离态(detached)。 简单理解就是,瞬时态指的是刚New 新建的一个对象,没有放在Session时,也没有存储在数据库中。 持久态,指这个对象存储在数据库中,并且存在于Session会话中。 而游离态指的是,这个对象存储在数据库中,但已经不存在于Session会话中。下面是比较官方的说法:

Hibernate三种实体状态(五)_数据库

二. 实体状态的简单举例

仍然采用上一章的例子。不会的,可以观看上一章。

/*
* 简单举例,三种状态,瞬时态,持久态,游离态的相关说明。
*/
@Test
public void testA(){
Session session=HibernateUtil.getSession();
Transaction transaction=session.beginTransaction();
User user=new User(); //是瞬时态
user.setUserName("两个蝴蝶飞");//瞬时态
user.setAge(24);
user.setSex("男");
user.setDescription("一个迷途知返的程序员"); //瞬时态
session.save(user); //session方法之后,user就是持久态
transaction.commit();
System.out.println("持久态描述为:"+user.getDescription());//持久态
session.close(); //关闭会话后 user就是游离态
System.out.println("游离态描述:"+user.getDescription());//游离态
}

运行之后,控制台输出:

Hibernate三种实体状态(五)_数据库_02


在数据库中会相应存储这条数据.

Hibernate三种实体状态(五)_数据库_03

三. 三种状态的相互转换

三种状态可以相互进行转换,其中关系图如下:

Hibernate三种实体状态(五)_hibernate_04


其中文字描述简单理解就是:

  1. 瞬时态转换成持久态可以通过: Session的 save()或者saveOrUpdate()方法。
  2. 持久态转换成瞬时态可以通过: Session的delete()方法。持久态转换成瞬时态可以通过: Session的delete()方法。
session.delete(user);   //以前,这种叫做删除态。也是网上看到的第四种状态.
// 虽然这种状态也可以取出属性,但不建议使用。逻辑上是不通的
System.out.println("瞬时态对象名称:"+user.getUserName());
  1. 持久态转换成游离态: 可以通过 close(), clear() 和evict() 方法。
session.close(); //关闭会话后 user就是游离态
session.clear(); //清理
session.evict(user); //驱逐
  1. 游离态转换成持久态: 可以通过update(); saveOrUpdate()和lock()方法。lock()是加锁的方法.
  2. 瞬时态转换成游离态: 加上标识符即可
User user=new User(); //瞬时态
user.setId(1); // 游离态
user.setUserName("两个蝴蝶飞"); //游离态
  1. 游离态转换成瞬时态:delete()方法 或者去除标识符。
    去除标识符,即user.setId(null); 即可。这也是要让实体类中属性设置成包装类的其中一个小原因。

四. 瞬时态的深入理解

/*
* 瞬时态 transient 的深入理解
*/
@Test
public void testB(){
Session session=HibernateUtil.getSession();
Transaction transaction=session.beginTransaction();
User user=new User(); //是瞬时态
user.setUserName("两个蝴蝶飞");//瞬时态
user.setAge(24);
user.setSex("男");
user.setDescription("一个迷途知返的程序员"); //瞬时态
session.save(user); //session方法之后,user就是持久态
transaction.commit();
}

通过save()方法,将瞬时态转换成持久态。

五. 持久态的深入理解

五.一 持久态之后继续追加数据

/*
* 将对象变成持久态之后,继续追加数据
*/
@Test
public void testPersistent1(){
Session session=HibernateUtil.getSession();
Transaction transaction=session.beginTransaction();
User user=new User(); //是瞬时态
user.setUserName("两个蝴蝶飞");//瞬时态
user.setAge(24);
user.setSex("男");
user.setDescription("一个迷途知返的程序员"); //瞬时态
session.save(user); //session方法之后,user就是持久态
user.setPassword("1234"); //继续追加数据
transaction.commit();
}

查看Sql语句为:

Hibernate三种实体状态(五)_数据库_05


先进行插入,后进行更新操作。 实际上,数据库中只生成了一条数据。

如果追加的数据是相同的数据,即:

@Test
public void testPersistent1(){
Session session=HibernateUtil.getSession();
Transaction transaction=session.beginTransaction();
User user=new User(); //是瞬时态
user.setUserName("两个蝴蝶飞");//瞬时态
user.setAge(24);
user.setSex("男");
user.setDescription("一个迷途知返的程序员"); //瞬时态
session.save(user); //session方法之后,user就是持久态
//user.setPassword("1234"); //继续追加数据
user.setAge(24); //设置相同的值
transaction.commit();
}

那么此时,只插入,并不会更新.

Hibernate三种实体状态(五)_hibernate_06


如果一个对象以及是持久化状态了,那么此时对该对象进行各种修改,或者调用多次update、save方法时,hibernate都不会发送sql语句,只有当事物提交的时候,此时hibernate才会拿当前这个对象与之前保存在session中的持久化对象进行比较,如果不相同就发送一条update的sql语句,否则就不会发送update语句。

五.二 提交后进行修改

/*
* 提交后,进行修改,也同样只会执行一条inset 语句
*/
@Test
public void testPersistent2(){
Session session=HibernateUtil.getSession();
Transaction transaction=session.beginTransaction();
User user=new User(); //是瞬时态
user.setUserName("两个蝴蝶飞");//瞬时态
user.setAge(24);
user.setSex("男");
user.setDescription("一个迷途知返的程序员"); //瞬时态
session.save(user); //session方法之后,user就是持久态
transaction.commit(); //先进行提交
user.setAge(24); //设置相同的值
transaction.commit();//再次进行提交
}

仍然只执行一条insert 语句。

Hibernate三种实体状态(五)_数据库_07

如果此时关闭Session了呢?

@Test
public void testPersistent2(){
Session session=HibernateUtil.getSession();
Transaction transaction=session.beginTransaction();
User user=new User(); //是瞬时态
user.setUserName("两个蝴蝶飞");//瞬时态
user.setAge(24);
user.setSex("男");
user.setDescription("一个迷途知返的程序员"); //瞬时态
session.save(user); //session方法之后,user就是持久态
transaction.commit(); //先进行提交
session.close(); //clear() 也是执行一条insert 语句
Session session1=HibernateUtil.getSession();
Transaction transaction1=session1.beginTransaction();
user.setAge(24); //设置相同的值
transaction1.commit();//再次进行提交
}

仍然会执行一条insert 语句。 这就是一级缓存的作用。

五.三 查询后修改

/*
* 先查询,后进行修改
*/
@Test
public void testPersistent3(){
Session session=HibernateUtil.getSession();
Transaction transaction=session.beginTransaction();
User user=session.get(User.class,4);
user.setAge(25); //设置不同值时 一条select,一条update
//user.setAge(24); //设置相同的值 只有一条select
transaction.commit();//再次进行提交
}

如果查询的值,即get(User.class,1000) 不存在时,会报空指针的错误. NullPointerException 。
如果设置的是不同的值,原先是24,那么会执行两种条件。一种是查询语句,另外一条是修改udpate 语句。
如果设置的是相同值,那么只执行一条select 查询语句。

五.四 先清空,后提交

@Test
public void testPersistent4(){
Session session=HibernateUtil.getSession();
Transaction transaction=session.beginTransaction();
User user=session.get(User.class,4);
user.setAge(25); //设置不同值时
session.clear(); //close()时也同样效果
transaction.commit();//再次进行提交
}

Hibernate三种实体状态(五)_数据_08


只执行一条查询语句.

当我们get出user对象时,此时user是持久化的对象,在session缓存中存在该对象,此时我们在对user进行修改后,然后调用session.clear()方法,这个时候就会将session的缓存对象清空,那么session中就没有了user这个对象,这个时候在提交事务的时候,发现已经session中已经没有该对象了,所以就不会进行任何操作,因此这里只会发送一条select语句。

六. 游离态对象的深入理解

六.一 save()对象并不能将其变成持久态

@Test
public void testDetached1(){
Session session=HibernateUtil.getSession();
Transaction transaction=session.beginTransaction();
User user=new User();
user.setId(24); //不存在24时,为一条插入语句
//user.setId(5); //存在5时,为一条插入语句
//user.setId(50) //很远的值
user.setUserName("测试游离态对象123");
session.save(user);
transaction.commit();//再次进行提交
}

此时,当设置了id的值之后,就变成了游离态对象了。此时,调用save()方法时,无论id设置了多少,无论是24(接下来的值),5(已经存在的值),50(离很远的值),此时save()保存的值,都是会按照顺序进行排序的,即

Hibernate三种实体状态(五)_数据库_09


是自定义的规则 ,即依次递增。并不是我们自己setId()的这个值。

Hibernate三种实体状态(五)_数据库_10


只执行一条插入语句。

六.二 执行update()语句

@Test
public void testDetached2(){
Session session=HibernateUtil.getSession();
Transaction transaction=session.beginTransaction();
User user=new User();
user.setId(5); //存在时,为一条插入语句
//user.setId(50) ;// 不存在这条数据
user.setUserName("测试游离态对象123");
session.update(user); //变成了持久态对象
user.setDescription("游离态对象的测试123");
transaction.commit();//再次进行提交
}

这里会执行一条update 语句.

Hibernate三种实体状态(五)_数据库_11


修改的,正是那条id=5的数据。

Hibernate三种实体状态(五)_hibernate_12


如果此时,设置的id并不存在的话。即

user.setId(50) //不存在这个id,会抛出异常

Hibernate三种实体状态(五)_数据库_13

六.三 修改Id编号

@Test
public void testDetached3(){
Session session=HibernateUtil.getSession();
Transaction transaction=session.beginTransaction();
User user=new User();
user.setId(5);
user.setUserName("测试游离态对象123");
session.update(user); //变成了持久态对象
user.setDescription("游离态对象的测试123");
user.setId(50); //修改id编号 抛出异常
transaction.commit();//再次进行提交
}

会抛出异常:

HHH000346: Error during managed flush [org.hibernate.HibernateException: identifier of an instance of com.yjl.pojo.User was altered from 5 to 50]

六.四 修改删除的对象

@Test
public void testDetached4(){
Session session=HibernateUtil.getSession();
Transaction transaction=session.beginTransaction();
User user=new User();
user.setId(5);
session.delete(user);
user.setUserName("测试游离态对象删除123");
user.setDescription("游离态对象的测试删除123");
transaction.commit();//再次进行提交
}

会执行删除语句:

Hibernate三种实体状态(五)_数据库_14


Hibernate三种实体状态(五)_数据_15

六.五 存在两个相同标识符的对象

@Test
public void testDetached5(){
Session session=HibernateUtil.getSession();
Transaction transaction=session.beginTransaction();
User user1=session.get(User.class,6);
User user2=new User();
user2.setId(6);
user2.setDescription("两个相同的id");
session.update(user2);
//session.merge(user2); // 应该使用merge()方法
transaction.commit();//再次进行提交
}

此时 ,会抛出异常

Hibernate三种实体状态(五)_hibernate_16


应该调用merge()方法.这个方法的作用就是解决一个持久化对象两分拷贝的问题,这个方法会将两个对象合并在一起成为一个对象。

Hibernate三种实体状态(五)_数据库_17


Hibernate三种实体状态(五)_数据_18


原先的数据会被更新,换成新的数据。

谢谢!!!


标签:Hibernate,实体,transaction,瞬时,session,三种,user,游离态,User
From: https://blog.51cto.com/u_13420484/5845484

相关文章

  • 通用继承实体类BaseEntityPlus
    @DatapublicclassBaseEntityPlusimplementsSerializable{privatestaticfinallongserialVersionUID=7621168359132150516L;/**创建时间*/@T......
  • java通过cglib动态生成实体bean的操作
    转载自:https://www.jb51.net/article/205882.htm maven依赖:12345678910<dependency>      <groupId>commons-beanutils</groupId>   ......
  • nuxt3引入element-plus的三种方法
    1、全部引入安装element-plus依赖npminstallelement-plus--save在nuxt3项目中plugins下新建一个element-plus.client.ts文件 在element-plus.client.ts文件中输......
  • LIS 最长递增子序列 三种求解方式
    1dp2二分3indextree 题目描述给出一个列表如[[6,7,],[5,4],[3,2]],表示木块的长和宽,当木块的长和宽不大于另个木块的长和宽时,就可以放在上面,此外数组还可以左右翻......
  • 说说关于Android使用Gson解析Json所需实体类的那些事~
    LZ-Says:技术,真的是日积月累,厚积薄发~前言目前解析json的方法有很多种,LZ个人认为使用Gson还是一种很不错的选择,因为使用Gson时,我们只需要考虑将json中参数和实体类属性一一对......
  • Hibernate简单注解开发和事务处理(四)
    勿以恶小而为之,勿以善小而不为--------------------------刘备劝诸君,多行善事积福报,莫作恶上一章简单介绍了Hibernate实现简单的CRUD操作和常见类(三),如果没有看过,​​请观......
  • Hibernate中hibernate.cfg.xml文件和Xxx.hbm.xml文件的详细解释(二)
    勿以恶小而为之,勿以善小而不为--------------------------刘备劝诸君,多行善事积福报,莫作恶上一章简单介绍了Hibernate开发环境的简单搭建及常见错误(一),如果没有看过,​​......
  • java :多线程实现的三种方式
    一、并行、串行、并发在了解java中多线程的三种实现方式之前,我们首先需要明白并行、串行、并发三个概念。1.并行:多个CPU同时处理多个任务;2.串行:单个CPU处理多个任务,当一......
  • 生成nuxt3项目的三种方法
    方法一:npxnuxiinitnuxt-app方法二:到github的nuxt仓库下的一个叫starter的项目中:https://github.com/nuxt/starter  点击code下载,之后安装依赖方法三:去官网......
  • 一些有用的 HTML 字符实体 < >"&
    ResultEntityName &nbsp;<<>>&&amp;""'&apos;¢&cent;£&pound;¥&yen;€&euro;©&copy;®&reg;     ......