一个实体有两个不同的主键 与 两个不同的实体引用了同一个连接
困扰了我很长时间的一个问题,今天终于解决了。下面我先把问题简要说一下:
?我们在项目把Hibernate的session进行了绑定,也就是说浏览器不关,一直用的都是同一个session。假如我从页面中传来一个order对象,要修改这个对象中的部分信息。则首先我要从数据库中查询出以前的这个对象来(这里把他付给oldOrder),然后将以前的对象中的某些属性付给页面中传来的order中,最后保存页面中传来的对象。
只要从数据库中查询出来对象,再保存,则会报下面这个错误:
org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.erp.pojo.orders.OrderInfo#17]
原因是oldOrder已经在session中了,从页面中传来的order的id和session中的id相同。它们就不可能在session中同时存在。
网上常用的解决办法有三种:
解决方法一:session.clean() ;(我从没有找到这个clean方法,我感觉应该是session.clear()才对)
解决方法二:session.refresh(object)
解决方法三:session.merge(object)
这三种方法都试过了,最后两个方法不起作用。clear()方法到时用了很长时间,原理是调用这个方法之后把session中的对象全部清空掉,但如果你的对象中有set或者list集合付给了order对象,那就麻烦了。它会报这个错误:
org.hibernate.HibernateException: Found two representations of same collection: com.erp.pojo.orders.TeamInfo._price
我是这样写的:order.setTeam(oldOrder.getTeam());报错的原因是TeamInfo类中有很多set集合,_price就是这么一个集合变量。
如果要清掉session只能用clone方法或者new一个新的set集合出来,但如果集合中有集合,有很多集合,那就麻烦了。这里我是用另外一种方法,在保存的时候重新创建一个session出来。
我用的ssh框架,但是思路都是相同的。下面是我现在的代码:
? Session session = this.getHibernateTemplate().getSessionFactory().openSession();
Transaction tr = session.beginTransaction();
tr.begin();
session.saveOrUpdate(order);
tr.commit();
session.close();
以前是这样写的:
try{
//添加或更新记录
this.getHibernateTemplate().saveOrUpdate(order);
}catch(SystemException e){
this.getSession().flush();
this.getSession().clear();
this.getHibernateTemplate().merge(order);
}
链接地址:http://hi.baidu.com/vaisu/blog/item/6cc1522451ab4f3fd50742c4.html