Hibernate通过update来处理游离状态对象

摘自圣思园hibernate18. 领域对象的三种状态深入详解- 25分钟

上一篇文章中讲到hibernate中对象的三种状态。
http://alleni123.iteye.com/admin/blogs/1977132

这里要说的就是通过update语句对游离状态进行持久化。在开发中是比较常用的一个方法。


先看一下hibernate文档对update方法的说明:

void update(Object object)

  Update the persistent instance with the identifier of the given detached instance. If there is a persistent instance with the same identifier, an exception is thrown. This operation cascades to associated instances if the association is mapped with cascade="save-update".

要理解的是中间那句"If there is a persistent instance with the same identifier, an exception is thrown"
这个意思其实是说, 如果我们执行
User u=new User(1,"allen");
User u2=(User)session.get(User.class,1);
session.update(u);

此时会抛出异常:
Exception in thread "main" org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.lj.zhang.User#1]
at org.hibernate.engine.internal.StatefulPersistenceContext.checkUniqueness(StatefulPersistenceContext.java:697)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:296)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:241)
at org.hibernate.event.internal.DefaultUpdateEventListener.performSaveOrUpdate(DefaultUpdateEventListener.java:55)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:90)
at org.hibernate.internal.SessionImpl.fireUpdate(SessionImpl.java:786)
at org.hibernate.internal.SessionImpl.update(SessionImpl.java:778)
at org.hibernate.internal.SessionImpl.update(SessionImpl.java:774)


这里看一下StatefulPersistenceContext的源码:
/**
* Attemps to check whether the given key represents an entity already loaded  with the current session.
* @param object The entity reference against which to perform the uniqueness  check
**/

public void checkUniqueness(EntityKey key, Object object) { //这里的参数是1和我们自定义的User对象。
   Object entity=getEntity(key), //Object entity=getEntity(key)执行之后entity被赋予了get获取的那个User对象,该对象被从session缓存中提取出来。
   if(entity==object)
   { throw new AssertionFailure ("object already associated, but no entry was found");}
    if(entity!=null){//由于entity!=null成立, 于是抛出NonUniqueObjectException。
   throw new NonUniqueObjectException(key.getIdentifier(), key.getEntityName());
    }

}



也就是说, 当我们要对持久化对象进行update(既更新数据库对象时),我们不应该通过get或者load从数据库读取该id的对象到session缓存中。

-Session的update()方法完成以下操作:
1. 把User对象重新加入到Session缓存中,使它变为持久化对象。
2. 计划执行一个update语句。 值得注意的是,Session只有在清理缓存的时候才会执行update语句,并且在执行时才会把User对象当前的属性值组装到update语句中。 因此,即使程序中多次修改了User对象的属性,在清理缓存时只会执行一次update语句。

猜你喜欢

转载自alleni123.iteye.com/blog/1977897