日期:2014-05-16  浏览次数:20437 次

hibernate操作数据库 update的问题 session.update() hibernateTemplate.update()
今天遇到了一个问题,简单描述下,我在dao层使用 hibernateTemplate.update(obj);时发现数据无法更新,但也未报任何异常信息(可能项目搭的不好),几经周折,使用session.update(obj);时成功更新数据,在update之前,我先load加载了该对象,上网查得资料是session或事务问题, 解决方式是使用 hibernateTemplate.merge(obj);成万全之策。
一下资料来自 http://hi.baidu.com/anypcao/item/6c73e10a21c72bce75cd3c7c

(无抄袭之意,只为保存参考学习)
session.update()主要对detached object有点作用。

1。对于persistent obj
session.beginTransaction();
Employee employee = session.load(Employee.class, new Integer(12));
session.setAge((byte)63);
session.update(employee); //employee 是一个persistent obj
   System.out.println("test flag");
tx.commit();
这段程序如果把net.sf.hibernate.impl.SessionImpl的log4j.logger打开,可以看到 session.update()位置处,hibernate打印一条object already associated with session,其他的什么也没干,这是因为对于persistent obj, hibernate可以依赖于dirtyChecking机制来更新对象。

2。对于transient obj
session.beginTransaction();
Employee employee = new Employee();
session.setAge((byte)63);
session.update(employee); //employee 是一个transient obj
   System.out.println("test flag");
tx.commit();
hibernate会在session.update()的时候发现是transient obj, 抛出HibernateException:The given object has a null identifier。但是如果给employee设置一个值得话employee.setId(new Integer(87)),hibernate在tx.commit()的时候发送update语句。update xxx set xxx=xxx where id=87, 由于数据库没有87的纪录,所以对数据库的状态不会有任何的影响。

3。对于detached obj
session.beginTransaction();
Employee employee = session.load(Employee.class, new Integer(12));
tx.commit();
session.close();
....
session.beginTransaction();
session.setAge((byte)63);
session.update(employee); //employee 是一个persistent obj
   System.out.println("test flag");
tx.commit();

   上面这段代码为了得到一个id为12的detached obj, 写的比较罗嗦。事实上我们如果在真正的应用中,知道某个Employee的id



下面是错误解决:
org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session:


于是我查询了一下资料,还终于在java Tutorials and Delelopment 的网站上找到了

Exception happens when you try to use session.update, session.lock
Solution

This exceptions happens when you did load an object allready with

session.get or session.load

and you try to reattach the object with

session.update or session.lock

Do not load an object to the session when you have allready a reference to it, you want to reuse.


Exception Message

org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [de.laliluna.hibernate.Concert#1]
at org.hibernate.engine.StatefulPersistenceContext.checkUniqueness(StatefulPersistenceContext.java:629)
at org.hibernate.event.def.AbstractReassociateEventListener.reassociate(AbstractReassociateEventListener.java:52)
at org.hibernate.event.def.DefaultLockEventListener.onLock(DefaultLockEventListener.java:59)

这个异常发生当你用session.load 或 session.get加载一个对象时 而又尝试着
session.update or session.lock 操作此对象

解决:
请不要用session加载对对象当你引用或再次使用该对象

由于我在做删除或修改数据操作时,而同时又查询,在查询中我没有关闭session 而造成 a different object with the same identifier value was already associated with the session



以下是具体内容。。额。。好多。。不用看。。具体原因不用管。总之看解决的办法。。很简单 解决办法:

    在数据访问层将public void update(User instance) {
    super.getHibernateTemplate().update(instance);
    } 的update 改成merge 就可以了。通俗吧。。易懂吧。。 public void update(User instance) {
    super.getHibernateTemplate().merge(instance);
    } 在这里记一笔。防止以后没记性。。