Hibernate持久态与脱管态对象的更新

  Hibernate将对象分为瞬时(transient)、持久(persistent)和脱管(detached)三种状态。

  使用new关键字构造的对象,都处于瞬时状态,经过save以后可以变成持久态,而由get或者load方法得到的对象,都处于持久态,而持久态对象在session结束以后,自动转入脱管态。

  对于持久态的对象,只要使用相应的setter方法改变其属性值,这些改变就会被侦测到,在调用session的flush方法时该对象的所有变更都会被更新到数据库中,因此,对于持久态的对象,是不需要使用update方法对对象进行更新的。

  对于脱管态的对象,使用setter方法对属性进行的变更不会被侦测到并自动应用到数据库,但是通过update方法可以将这些变更应用到数据库,并使对象重新进入持久态,而使用merge方法,同样可以将变更应用到数据库,但对象仍然处于脱管状态。

  对于update、saveOrUpdate和merge三个方法,其实是有较大的区别的,有时候理解有误可能导致预料之外的结果。

  saveOrUpdate方法的实际操作是:

  1. 如果对象已经处于持久态,不作任何操作,返回。
  2. 如果对象与另一个和session相关的对象拥有相同的标识符,则抛掷异常。
  3. 如果对象没有为标识符属性赋值,则save。
  4. 如果对象的标识符属性是用户调用setter方法赋值的,则save。
  5. 如果对象的版本属性与赋予新实例对象的值相同,则save。
  6. 否则update对象。

  update方法的实际操作是:

 

  1. 如果对象已经处于持久态,不作任何操作,返回。
  2. 如果对象与另一个和session相关的对象拥有相同的标识符,则抛掷异常。
  3. 如果对象没有为标识符属性赋值,则抛掷异常。
  4. 如果对象的标识符属性是用户调用setter方法赋值的,则抛掷异常。
  5. 如果对象的版本属性与赋予新实例对象的值相同,则抛掷异常。
  6. 否则更新对象。

  merge方法的实际操作是:

  1. 如果有一个持久态对象与之具有相同标识符,则将这个对象的属性应用到相应的持久态对象上。
  2. 否则load产生一个持久态对象,并将属性应用到这个持久态对象上。
  3. 返回持久态的对象。
  4. 传入merge方法的对象仍然处于脱管态或者瞬时态。