getHibernateTemplate().update()异常分析与解决(NonUniqueObjectException 异常)

来源:互联网 发布:养什么蛇不犯法 知乎 编辑:程序博客网 时间:2024/04/30 23:31
先来看看baseDao中updateObject的实现:
Java代码  收藏代码
  1. public void updateObject(T o) {  
  2.                 getHibernateTemplate().update(o);  
  3.                 getHibernateTemplate().flush();  
  4.         }  
 
可以看出baseDao是通过直接调用hibernate的session.update(Object  object)方法来对数据库进行更新的。而该方法在执行时,如果在session的缓冲区中存在与传入对象object有相同id的PO对象的话,就会抛出org.hibernate.NonUniqueObjectException 异常。

了解了异常的来源,在回头来看项目,要实现的功能情景如下:
   1.在页面单击某条记录的修改按钮;
   2.在Action中返回该记录的信息并显示在页面上供用户进行修改;
   3.用户修改完后单击确定按钮提交到Aciton;
   4.Action对提交的信息通过service调用dao方法进行update操作。
现在我们假设要修改的数据的id为5,在上面1、2步中,id为5的PO(persistent object)对象从数据库中调入session的缓冲区用于前端的展示;当执行4时,Action中的对象是从表单提交上来的VO(value object)对象,它的id也是5,那么在这时执行update方法时,由于在session的缓冲中已经存在了id为5的PO,那么就会抛出org.hibernate.NonUniqueObjectException 异常。

解决办法:
    1。既然是由于缓冲区里存在了相同id的对象导致异常的抛出,那么在update之前清空缓冲区不就行啦,于是将baseDao中updateObject方法修改成如下:
Code代码  收藏代码 这个粒子是万能例子,什么时候都能保证无误
  1. public void updateObject(To) {  
  2.                 getHibernateTemplate().clear();  
  3.                 getHibernateTemplate().update(o);  
  4.                 getHibernateTemplate().flush();  
  5.         }  

 

修改后执行果然没有异常抛出,数据也修改成功。

    2。在网上还有一种解决办法,就是使用hibernate3新增的方法,session.merge()。该方法在执行时会先到session缓冲中寻找相应的PO,并将新对象赋值过去。于是修改后的方法变为:

Code代码  收藏代码
  1. public void updateObject(T o) {  
  2.                 getHibernateTemplate().merge(o);  
  3.                 getHibernateTemplate().flush();  
  4.         }  


执行后数据也能成功修改。

Hibernate3的缺点,一级缓存的强引用的问题,所以在做批量查询和插入操作的时候需要执行session.flush和session.clear两个操作。

flush(),使用 

(在spring声明事务的情况下)

若A引用 了B,现在同时增加这两个类,如果你不用的hibernate自动处理机制 ,则需要在save(B)后,调用 flush()强行的写入数据库,再将返回的主键写入A中,再save(A),否则将报出找不到B的错误,这是因为声明式事务的方法是在方法结束后一起提交,因此会出现异常。

 

 

clear() 使用

在实际过程中可能会出现这样的情况,需要创建A,A完全的copy自B(此时的B是根据ID get()得到的),而A.B又是属于同一张表的实体,因此在save(A)时,会出现异常,提示你有两个相同的数据,却是不同的标识,异常抛出后无法正常的保存,

那怎么解决呢,这时候你就需要在save()执行前加上一个clear()了,如:

   getHibernateTemplate().clear();

getHibernateTemplate().save(t11);

 


0 0