hibernate a different object

http://blog.csdn.net/majian_1987/article/details/51726569

 

http://blog.csdn.net/lang_man_xing/article/details/7572964

转自 http://blog.csdn.net/zhongxianyao/article/details/12294011 

        在说这两者的区别时,有必要把hibernate对象三种状态说一下:

        翻译自Hibernate的参考文档

        Hibernate定义并支持下列对象状态(state):
        瞬时(Transient) - 由new操作符创建,且尚未与Hibernate Session 关联的对象被认定为瞬时(Transient)的。瞬时(Transient)对象不会被持久化到数据库中,也不会被赋予持久化标识(identifier)。 如果瞬时(Transient)对象在程序中没有被引用,它会被垃圾回收器(garbage collector)销毁。 使用Hibernate Session可以将其变为持久(Persistent)状态。(Hibernate会自动执行必要的SQL语句)
        持久(Persistent) - 持久(Persistent)的实例在数据库中有对应的记录,并拥有一个持久化标识(identifier)。 持久(Persistent)的实例可能是刚被保存的,或刚被加载的,无论哪一种,按定义,它存在于相关联的Session作用范围内。 Hibernate会检测到处于持久(Persistent)状态的对象的任何改动,在当前操作单元(unit of work)执行完毕时将对象数据(state)与数据库同步(synchronize)。 开发者不需要手动执行UPDATE。将对象从持久(Persistent)状态变成瞬时(Transient)状态同样也不需要手动执行DELETE语句。
        脱管(Detached) - 与持久(Persistent)对象关联的Session被关闭后,对象就变为脱管(Detached)的。 对脱管(Detached)对象的引用依然有效,对象可继续被修改。脱管(Detached)对象如果重新关联到某个新的Session上, 会再次转变为持久(Persistent)的(在Detached其间的改动将被持久化到数据库)。 这个功能使得一种编程模型,即中间会给用户思考时间(user think-time)的长时间运行的操作单元(unit of work)的编程模型成为可能。 我们称之为应用程序事务,即从用户观点看是一个操作单元(unit of work)。

 

        好了,进入正题,明白了3种状态,我们来说一下什么时候要用update,什么时候要用merge

        update():如果你确定在当前session的会话里不存在一个与要进行update操作有相同标识符(主键)的持久化对象,那么调用update()。这句话理解起来有点绕,后面举个例子就明白了。

        merge():如果你在任何时候修改了数据都想把数据保存到数据库中,那么就调用merge()。

 

        例子程序片段:

        有一个Person对象,里面有两个属性,id和name

 

[java] view plain copy
 
 print?
  1. Session session = sessionFactory.openSession();   
  2. Transaction tx = session.beginTransaction();   
  3. Person person = (Person) session.get(Person.class"15");  
  4. tx.commit();   
  5. session.clear();  
  6. session.close();  
  7.   
  8. System.out.println(person.getId());  
  9. person.setName("jasper");  
  10. Session session2 = sessionFactory.openSession();   
  11. Transaction tx2 = session2.beginTransaction();   
  12. Person person2 = (Person) session2.get(Person.class"15");  //是不是感觉这句代码有点多余,问题就出在这里  
  13. //session2.update(person);  //抛出 org.hibernate.NonUniqueObjectException  
  14. //session2.saveOrUpdate(person);  //抛出 org.hibernate.NonUniqueObjectException  
  15. session2.merge(person);  //成功执行  
  16. tx2.commit();   
  17. session2.close();  

 

        当调用update或saveOrUpdate操作时,抛出了异常信息“org.hibernate.NonUniqueObjectException”,不是“独一无二”的对象。为什么会抛出这个错误呢?上面的person2调用了get方法,所以person2是一个持久化对象,当在session还没有关闭的时候对person2做的任何修改,都会保存到数据库中;person要执行更新操作,但由于它是一个脱管对象,那么就需要跟数据库重新取得联系,需要从数据库获取数据,hibernate会查找当前是否关于这个对象的副本,刚好有个person2(但又不知person2是否修改了且保存到了数据库),与其保存这可能没用的数据,还不如直接报错来得直接。这里调用update和saveOrUpdate类似。

 

        还有update与merge的一点不同是:update是直接发出“sql update”语句,而merge会先发出“sql select”语句,如果没有查询到结果,那么执行save操作,如果查询到相关结果,则判断对应字段是否有发生改变,如果改变了,则发出“sql update”语句,否则什么也不做。这一方面,merge就和saveOrUpdate相同。

猜你喜欢

转载自lanrikey.iteye.com/blog/2346743