Hibernate持久化对象的三种状态

文章目录

1. 持久化对象三种状态的概述

Hibernate为了更好的来管理持久化类,特将持久化类分成了三种状态。在Hibernate中持久化的对象可以划分为三种状态,分别是瞬时态、持久态和脱管态,一个持久化类的实例可能处于三种不同状态中的某一种,三种状态的详细介绍如下:

  • 瞬时态(transient)
    瞬时态也称为临时态或者自由态,瞬时态的实例是由new命令创建、开辟内存空间的对象,不存在持久化标识OID(相当于主键值),尚未与Hibernate Session关联,在数据库中也没有记录,失去引用后将被JVM回收。瞬时状态的对象在内存中是孤立存在的,与数据库中的数据无任何关联,仅是一个信息携带的载体。
  • 持久态(persistent)
    持久态的对象存在持久化标识OID,加入到了Session缓存中,并且相关联的Session没有关闭,在数据库中有对应的记录,每条记录只对应唯一的持久化对象,需要注意的是,持久态对象是在事务还未提交前变成持久态的。
  • 脱管态(detached)
    脱管态也称离线态或者游离态,当某个持久化状态的实例与Session的关联被关闭时就变成了脱管态。脱管态对象存在持久化标识OID,并且仍然与数据库中的数据存在关联,只是失去了与当前Session的关联,脱管状态对象发生改变时Hibernate不能检测到。

2. 持久化对象的三种状态案例

为了帮助大家更好的理解持久化对象的三种状态,下面通过一个案例来详细说明。

public void demol ()(
	Configuration configuration = new Configuration().configure();
	SessionFactory sessionFactory = configuration.buildSessionFactory();
	Transaction transaction = session.beginTransaction();
	
	Customer customer = new Customer();//瞬时态对象:没有持久化标识 ID,没有被 session管理
	
	customer.setCust_name("joker");
	Serializable id = session.save(customer);//持久态对象:有持久化标识 ID,被 session管理
	
	transaction.commit();
	session.close();
	sessionFactory.close();
	System.out.printin(customer);//托管态对象:有持久化标识 ID,没有被 session管理
}

customer对象由new关键字创建,此时还未与Session进行关联,它的状态称为瞬时态。在执行session.save(customer);操作后,customer对象纳入了Session的管理范围,这时的customer对象变成了持久态对象,此时Session的事务还没有被提交。程序执行完commit操作并关闭了Session后,customer对象与Session的关联被关闭,此时customer对象就变成了脱管态。

3. 三种状态的转换

上面已经了解了Hibernate持久化对象的三种状态,然而这三种状态是可以通过一系列方法进行转换的,下面就来介绍一下三种状态之间如何转换。
《Hibernate持久化对象的三种状态》
从图中可以看出,当一个对象被执行new关键字创建后,该对象处于瞬时态。当对瞬时态对象执行Session的save或saveOrUpdate方法后,该对象将被放入Session的一级缓存,对象进入持久态。当对持久态对象执行evict、closed、clear操作后,对象进入脱管态。当直接执行Session的get、load、find、iterate等方法从数据库里查询对象时,查询到的对象也处于持久态。当对数据库中的纪录进行 update、saveOrUpdate、lock等操作后,此时脱管态的对象就过渡到持久态。由于瞬时态和脱管态的对象不在session的管理范围,所以会在一段时间后被JVM回收。

持久化对象的三种状态可以通过调用Session中的一系列方法实现状态间的转换,具体如下。

3.1 瞬时态转换到其他状态

瞬时态的对象由new关键字创建,瞬时态对象转换到其他状态总结如下:

  • 瞬时态转换为持久态:执行Session的save、saveOrUpdate方法。

  • 瞬时态转换为脱管态:为瞬时态对象设置持久化标识OID。

  • 由于持久化对象状态演化图中没有涉及到瞬时态转换到脱管态的情况,这里做下简要的说明,脱管态对象存在OID,但是没有Session的关联,也就是说脱管态和瞬时态的区别就是OID有没有值,所以可以通过为瞬时态对象设置OID,使其变成脱管态对象。

    Customer customer = new Customer();//瞬时态
    customer.setCust_id(1);//托管态
    

3.2 持久态对象转换到其他状态

持久化对象可以直接通过Hibernate中Session的get、load方法,或者Query查询从数据库中获得,持久态对象转换到其他状态总结如下:

  • 持久态转换为瞬时态:执行Session的delete方法,需要注意的是被删除的持久化对象,不建议再次使用。
  • 持久态转换为脱管态:执行Session的evict、close、clear方法。evict方法用于清除一级缓存中某一个对象。close方法用于关闭Session,清除一级缓存。clear方法用于清除一级缓存的所有对象。

3.3 脱管态对象转换到其他状态

脱管态对象无法直接获得,是由其他状态对象转换而来的,脱管态对象转换到其他状态总结如下:

  • 脱管态转换为持久态:执行Session的update、saveOrUpdate、lock方法。

  • 脱管态转换为瞬时态:将脱管态对象的持久化标识OID设置为null。

  • 由于持久化对象状态演化图中没有涉及到脱管态转换到瞬时态的情况,这里做下简要的说明,跟瞬时态转换到脱管态的情况相似,脱管态和瞬时态的区別就是OID有没有值,所以可以通过将脱管态对象的OID设置为null,使其变成瞬时态对象。例如在session.close();操作后,加入代码

    customer.setCust_id(null);
    

    customer对象将由脱管态转换为瞬时态。

4. 持久化对象能够自动更新数据库

持久化对象有一个非常重要的特征:持久化对象可以自动更新数据库。下面通过一个案例来详细说明。

public void demo2 ()(
	Configuration configuration = new Configuration().configure();
	SessionFactory sessionFactory = configuration.buildSessionFactory();
	Transaction transaction = session.beginTransaction();
	
	Customer customer = session.get(Customer.class, 1L);//持久态对象
	customer.setCust_name("李四");
	
	//session.update(customer); //不用手动调用 update方法就可以更新
	
	transaction.commit();
	session.close();
	sessionFactory.close();
}

执行测试我们会发现,我们并没有手动调用update方法,Hibernate就可以将数据自动更新了。持久态对象就有这样的一个功能,持久态对象之所以有这样的功能其实都依赖了Hibernate的一级缓存,有关Hibernate的一级缓存将在下一篇博文中详细说明。

    原文作者:weixin_45990046
    原文地址: https://blog.csdn.net/weixin_45990046/article/details/103499136
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞