【问题标题】:Difference between Hibernate update by Session.update and HibernateTemplate.merge通过 Session.update 和 HibernateTemplate.merge 更新 Hibernate 的区别
【发布时间】:2011-03-28 12:45:56
【问题描述】:

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

    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);

这两种方法的作用相同。我想知道哪个更好、更安全以及为什么。谢谢。

【问题讨论】:

标签: java hibernate


【解决方案1】:

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

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

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

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

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

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

【讨论】:

  • 谢谢。如何知道对象是否附加到会话?
  • 我已经编辑了答案以涵盖持久和分离的对象
  • 非常感谢。很好的解释:)。
【解决方案2】:

什么是没有任何代码示例的 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(),我们会得到以下异常:

org.hibernate.NonUniqueObjectException:具有相同标识符值的不同对象已与会话关联:[com.spring.model.Organization#100624]

一个。我们在这里进行合并:

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

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

三。如果我们在 org1 上合并,我们就会得到 org。

b.这将始终返回 false,表示合并后,org 仍处于 DETACHED 状态

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

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

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

【讨论】:

    【解决方案3】:

    合并是否跟随

    Merge 有智能。它在实际合并之前有很多预检查(如果需要)

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

    在哪里作为 session.update

    1. 如果对象是瞬态的,则抛出异常。
    2. 如果 Object 已分离,它只会触发 UPDATE 查询,而不考虑对象的数据更改。

    session.merge 比更新昂贵

    【讨论】:

    • 感谢您的解释:-)
    【解决方案4】:

    基本区别是:

    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】:

      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);
      

      希望你清楚......,实际上更新和合并方法会在我们一次又一次地将同一个对象加载到数据库中时出现,就像上面一样。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-02-06
        • 2011-11-17
        • 2011-02-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多