Session.update和HibernateTemplate.merge之间的Hibernate更新之间的区别

时间:2011-03-28 12:45:56

标签: java hibernate

我看到了更新操作的类型: 第一:

    getHibernateTemplate().execute(new HibernateCallback() {
        public Object doInHibernate(Session session) {  
            session.flush();
            session.setCacheMode(CacheMode.IGNORE);
            SomeObject ss = (SomeObject) session.get(SomeObject.class, id);
            long next = ss.getAndIncrement();
            session.update(ss);
            session.flush();
            return null;
        }
    });

其次

    SomeObject ss = loadSomeObject(); 
    long next = ss.getAndIncrement();
    getHibernateTemplate.merge(ss);

这两种方法也是如此。我想知道哪一个更好,更安全,为什么。谢谢。

6 个答案:

答案 0 :(得分:13)

在第一个操作中,对象ss 附加到会话。在第二个操作中,其分离。因此,如果您有附加对象,则可以使用更新。如果你有一个分离的对象,那么使用合并首先将对象加入会话,然后进行更新

编辑:有关附加(持久)和分离对象的信息:

Hibernate定义并支持以下对象状态:

Transient - 如果一个对象刚刚使用new运算符进行实例化,并且它与Hibernate会话无关,则该对象是瞬态的。它在数据库中没有持久表示,并且没有分配标识符值。如果应用程序不再持有引用,则垃圾收集器将销毁瞬态实例。使用Hibernate Session使对象持久化(让Hibernate处理需要为此转换执行的SQL语句)。

持久性 - 持久性实例在数据库中具有表示形式和标识符值。它可能刚刚被保存或加载,但是,它定义在Session的范围内。 Hibernate将检测对处于持久状态的对象所做的任何更改,并在工作单元完成时将状态与数据库同步。当对象应该是瞬态的时,开发人员不会执行手动UPDATE语句或DELETE语句。

分离 - 分离的实例是一个持久的对象,但其会话已关闭。当然,对对象的引用仍然有效,甚至可以在此状态下修改分离的实例。可以在稍后的时间点将分离的实例重新附加到新的会话,使其(以及所有修改)再次持久化。此功能为需要用户思考的长时间运行工作单元启用编程模型。我们称之为应用程序事务,即从用户的角度来看工作单元。

答案 1 :(得分:7)

什么是没有任何代码示例的API?

SessionFactory sf =         ctx.getBean("hibernateSessionFactory",SessionFactory.class);
Session session = sf.openSession();
Transaction t = session.beginTransaction();
try {
   Session s2 = sf.openSession();
    Organization org = (Organization)s2.get(Organization.class,100624l);//1
    org.setOrgName("org");
    s2.close();//2
   Organization org1 =  (Organization)session.get(Organization.class,100624l);//3
    org.setOrgName("testOrg");
   org1.setOrgName("org");//a
    session.merge(org);//4
    System.out.println(org == org1);//b 
     t.commit();
} catch (HibernateException e) {
  t.rollback();
  throw e;
}finally{
      session.close();
 }
  1. 加载第一个实例并使其持久化。
  2. 该实例已分离。
  3. 已加载另一个实例
  4. 执行此操作时,有2个相同对象的实例 在会话中(org和org1) - org被分离并且org1是持久的 如果我们在那里执行update()或saveOrUpdate(),我们会得到以下异常:
  5. org.hibernate.NonUniqueObjectException:具有相同标识符值的其他对象已与会话关联:[com.spring.model.Organization#100624]

    一个。我们在这里合并:

    予。合并分离对象+持久对象的状态。

    II。如果发生冲突,合并的对象将获胜,就像在这种情况下,保存的值将是:testOrg

    III。如果我们在org1上合并,我们就会得到组织。

    湾这将始终返回false,这意味着后合并,org仍然处于DETACHED状态

    我希望差异化。现在很清楚。

    摘要: 如果会话中有同一个对象的2个实例(一个是分离的,一个是持久的),saveOrUpdate()或update()将抛出异常

    merge()不会抛出异常,但会在合并更改时保存对象。

答案 2 :(得分:3)

答案 3 :(得分:2)

遵循合并

合并有智慧。它在进行实际合并之前有很多预检(如果需要)

  1. 如果Object是瞬态的,它只是触发INSERT查询使对象持久化(附加到会话)
  2. 如果分离了Object,则触发select查询以检查数据是否已修改   如果被修改,则触发UPDATE查询,否则只是忽略合并任务。
  3. 其中session.update

      如果对象是暂时的,则
    1. 抛出异常。
    2. 如果分离了对象,它只会触发UPDATE查询,而不管对象的数据更改。
    3. session.merge比更新

答案 4 :(得分:1)

基本区别是:

Merge()并不关心会话是持久的还是分离的...它只会更新而不考虑会话。

如果update(),它会抛出类似org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session.

的异常

这里用一个很好的例子来解释:

http://www.java4developer.com/difference-between-update-and-merge-in-hibernate/

答案 5 :(得分:0)

hibernate中的update()和merge()方法都用于将处于分离状态的对象转换为持久状态。但没有什么区别。让我们看看在什么情况下将使用哪种方法。 让我们举个例子

SessionFactory factory = cfg.buildSessionFactory();
Session session1 = factory.openSession();

Employee s1 = null;
Object o = session1.get(Employee.class, new Integer(101));
s1 = (Student)o;
session1.close();

s1.setSSN(97);

Session session2 = factory.openSession();
Employee s2 = null;
Object o1 = session2.get(Employee.class, new Integer(101));
s2 = (Student)o1;
Transaction tx=session2.beginTransaction();

session2.merge(s1);
SessionFactory factory = cfg.buildSessionFactory();
Session session1 = factory.openSession();

Employee s1 = null;
Object o = session1.get(Employee.class, new Integer(101));
s1 = (Employee)o;
session1.close();

s1.setMarks(97);

Session session2 = factory.openSession();
Employee s2 = null;
Object o1 = session2.get(Employee.class, new Integer(101));
s2 = (Employee)o1;
Transaction tx=session2.beginTransaction();

session2.merge(s1);

希望你很清楚......实际上,当我们一次又一次地将相同的对象加载到数据库中时,更新和合并方法将会出现,如上所述。