Hibernate 会话中保存、更新、保存或更新、合并方法之间的差异?

Hibernate 会话中保存、更新、保存或更新、合并方法之间的差异?,hibernate,Hibernate,我对Hibernate还不熟悉,上周已经完成了Hibernate教程。我对会话类中的save、update、saveOrUpdate和merge方法有一些疑问。这些是: 保存方法:用于在数据存储中插入新创建的对象。(对于此项,基本上标识符值为0)。就像我创建一个新客户并调用save操作一样,它将把它保存在数据存储中并生成标识符 这是正确的吗?如果我们在已经持久化的对象上调用save,不确定会发生什么 更新方法:用于更新数据存储中已经存在的持久对象。(基本上,标识符值将是一些非零值)。就像我加载

我对Hibernate还不熟悉,上周已经完成了Hibernate教程。我对会话类中的save、update、saveOrUpdate和merge方法有一些疑问。这些是:

  • 保存方法:用于在数据存储中插入新创建的对象。(对于此项,基本上标识符值为0)。就像我创建一个新客户并调用save操作一样,它将把它保存在数据存储中并生成标识符

    这是正确的吗?如果我们在已经持久化的对象上调用save,不确定会发生什么

  • 更新方法:用于更新数据存储中已经存在的持久对象。(基本上,标识符值将是一些非零值)。就像我加载一个新客户并在更新某个字段值后调用更新操作一样,它将在数据存储中更新它

    根据我的理解,它应该会失败,但有一些例外,因为根据API更新是针对分离对象的。这是正确的吗?如果是,我们应该调用什么来更新同一会话中的对象(我的意思是如果对象未分离)。另一点是:如果我们在新创建的对象上调用update,将会发生什么

  • saveOrUpdate方法:它将根据未保存的值检查调用上述任一方法(必须根据标识符零值或非零值进行检查,对吗?),因此,如果我们有持久的客户对象,并且我们更新了他的姓氏并创建了一个新帐户,那么saveOrUpdate将处理它

    我理解对了吗

  • 合并方法:它的作用类似于更新,但在这里,如果会话中已存在具有相同标识符的持久对象,它将更新持久对象中分离的对象值并保存它

    但是,如果当前没有与会话关联的持久实例,这将从数据存储中加载持久对象,然后在加载的持久对象中更新分离对象的值,然后更新它

    我也收到了吗


    • 您的所有评估都完全正确。你明白了

      对于第一个问题,如果我没记错的话,
      save
      专门做了一个插入。因此,再次调用save将导致数据库中出现另一行


      对于第二个问题,
      update
      更新会话中的对象。因此,如果对象在会话中,它将更新。如果对象不在会话中,则应调用merge。我相信为分离的实例调用
      update
      会导致异常。

      大多数事情都是正确的,但update的工作原理与您描述它的方式略有不同。如果对象在会话中(即持久),则完全不需要更新。Hibernate处理刷新会话时对会话中对象的任何更改的持久化。对它们调用update不会起任何作用(并且可能会导致性能损失;我不确定)

      Update设计用于在分离的对象上调用,即那些现在位于加载它们的会话之外的对象@hvgotcodes解释似乎不正确,因为只有当对象不在会话中时才应该调用update。如果对象的实例已在会话中,则更新可能失败。在这种情况下,应该使用Merge。它将分离对象的更改与会话中的对象(如果存在)合并。如果会话中没有对象,它将创建一个新对象

      通常情况下,您可以完全避免调用update/merge,但如果最终不得不调用一个,merge将处理更广泛的情况。我的理解是,使用更新的唯一原因是为了更好的性能,假设您知道它不会出错

      对其他一些hibernate方法也有很好的总结


      编辑:我只是想说合并和更新之间的区别比我原来说的要多。Update将给定的实体修改为持久性,而merge将返回一个新的持久性实体。对于合并,您应该扔掉旧对象。另一个区别是merge在决定是否写入其数据之前,通过从DB中选择来执行脏检查,而update总是将其数据持久化到DB中,不管它是否脏

      可能还有其他一些小差别。通过记录生成的SQL来测试Hibernate行为总是很好的,因为行为并不总是与文档匹配,至少在我的经验中是这样。

      session.update()-它用于从Hibernate会话加载对象Person1的场景。现在它正在应用程序中使用-可能也在客户端,已经更新。我们想再次拯救它。我们知道数据库中的Person对象并没有做任何更改。所以我们可以简单地使用update

      session.merge()-在上述场景中,如果在保存更改的Person1对象之前对person数据进行了更改,那么我们应该使用merge。它将合并更改

      session.save()-可用于保存新对象。它返回可序列化的标识

      session.persist()-它与save()相同,但是void方法,不返回任何内容

      session.saveOrUpdate()-此方法适用于新对象和旧对象。若对象是新的,它将像简单保存一样工作;若对象已经是持久的,它将像更新一样工作

      session.lock()-它仅用于锁定对象,也可以说是检查对象的版本。它不是用来更新对象的。只有当您确定数据库中的对象状态尚未更改时,才应使用它重新附加对象。否则,它可能会覆盖更改关于这一点,请提供更多信息。

      update()
      用于分离的对象和瞬态对象。如果在持久对象上调用,它将抛出一个
      ununiqueobjectexception
      ,这将通过
      merge()
      SessionFactory factory = cfg.buildSessionFactory();
      Session session1 = factory.openSession();
      
      Student student1 = null;
      Object object1 = session1.get(Student.class, new Integer(101));
      student1 = (Student)object1;
      session1.close();
      
      student1.setMarks(97);// -->object will be in some RAM location, not in the session1 cache
      
      Session session2 = factory.openSession();
      Student student2 = null;
      Object object2 = session2.get(Student.class, new Integer(101));
      student2 = (Student)object2;
      Transaction tx=session2.beginTransaction();
      
      session2.merge(student1);