Hibernate持久化对象的状态

Hibernate持久化对象支持三个对象状态:
瞬态:当用new关键字创建对象时,这个对象还没有与Hibernate Session关联,那么这个对象就可以被认为是处于瞬态。处于瞬态的对象不会被持久化到数据库中,也不会被赋予持久化标识。如果这个对象长时间没有被引用,瞬态对象将被垃圾回收机制销毁。使用Hibernate Session可以将瞬态对象变为持久化状态。
持久化:持久化实例在数据库中有对应的记录,并拥有一个持久化的标识(identifier)。持久化的实例可以是刚刚保存的,也可以是刚刚被加载的,无论哪一种,持久化对象都必须与指定的Hibernate Session关联,没有与Hibernate Session关联的对象实例都不能称为处于持久化状态。Hibernate会检测处于持久化状态对象的改动 ,在当前操作执行完成时把对象写入数据库。开发者不需要手动UPDATE。
脱管:如果一个对象实例曾经处于持久化状态,但与之关联的Hibernate Session被关闭,该对象就变成脱管状态。脱管状态的对象,依然拥有有效引用,该对象可以继续被修改。如果脱管对象重新与Hibernate Session关联,那么该对象就又变成了持久化状态,并且在脱管状态下的改动也不会丢失,可以被写入数据库。因为这个功能,逻辑上的长事务成为可能,它被称为应用程序事务。特性是处于脱管状态的对象,在改动时无需锁定数据库,这样性能不会降低。
Hibernate 对象状态演化图:
这里写图片描述

改变对象为持久化状态的方法:
Serializable save(Object obj): 将obj对象变为持久化状态,该对象的属性将被保存到数据库。
void persist(Object obj): 将obj对象变为持久化状态,该对象的属性将被保存到数据库。
Serializable save(Object obj,Object pk): 将obj对象保存到数据库,保存到数据库时指定主键值。
void persist(Object obj,Object pk): 将obj对象转化为持久化状态,保存到数据库时,指定主键值。
save()与persist()方法的区别:使用save()方法保存持久化对象时,该方法返回该持久化对象的标识属性值(对应记录的主键值);但用persist()保存持久化对象时,该方法没有任何返回值,因为save()方法需要立即返回持久化对象的标识属性值,所以save()方法会立即将持久化对象对应的对象属性数据插入数据库。而persist()则保证当它在一个事务外部被调用时,并不立即转换成insert语句。

Object load(Object.class,Object pk):load()方法用于加载一个持久化实例,这种加载就是根据持久化类的标识属性值加载持久化实例,也就是从数据库中根据主键值读取一条记录。
Object get(Object.class,Object pk …) : get()方法基本与load()方法一样;
load()与get()的不同:
如果在没有标识属性值的记录,load()方法将可能抛出HibernateException异常,说可能是因为如果我们在类映射文件中指定了延迟加载,则load()会返回一个未初始化的代理对象,这个代理对象没有装载数据记录,直到程序调用该代理对象的方法时,Hibernate才会去访问数据库;get()虽然也是根据标识属性值加载持久化实例,但它会立即访问数据库,如果没有对应的记录,会返回null,而不是代理对象。

load()对持久化实例做的改动在Session flush之前会被自动保存到数据库,无须程序调用其它方法(不需要调用update方法)来修改持久化。但如果我们调用实例的setter方法改变它的属性,Hibernate会在Session flush之前生成 一条带where条件的update语句。 对于一个曾经持久化过的、但已经没有被Hibernate Session管理的持久化对象,也就是处于脱管状态的对象,如果要重新持久化,保存修改后的数据,必须用一个新的Hibernate Session来保存。提供的方法有update()、merge()、updateOrSave()。 update()与updateOrSave()方法的区别: update()是用来保存持久化状态对象的,但如果不清楚该对象是否曾经持久化过,就可以用updateOrSave()方法,它会自动判断该对象是否曾经持久化过,曾经持久化过用update()方法,没有用save()方法。 update()与merge()方法的区别: update()方法会将参数中的对象持久化,merge()不会,也就是不会受Session管理。