Session中的save,update,saveOrUpdate,merge方法之间的差异?

时间:2011-09-19 18:11:35

标签: hibernate

我是Hibernate的新手,上周经历了Hibernate教程。我对Session类中的方法save,update,saveOrUpdate和merge有一些疑问。这些是:

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

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

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

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

  • saveOrUpdate方法:它将基于未保存值检查调用上述任何一个(它必须根据标识符零或非零值进行调用,对吧?)所以如果我们有持久客户对象,我们更新他的姓氏并创建一个新帐户,然后saveOrUpdate将负责处理。

    我理解正确吗?

  • 合并方法:它会像更新一样,但是如果会话中已经有一个具有相同标识符的持久对象,它将更新持久对象中的分离对象值并保存它。

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

    我也明白了吗?

7 个答案:

答案 0 :(得分:30)

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

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

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

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

编辑:我只是认为我应该说合并和更新之间的差异比我原先说的要多。 Update将给定实体修改为持久性,而merge则返回新的持久性实体。对于合并,你应该扔掉旧的对象。另一个区别是合并在决定是否写入数据之前通过从DB中选择进行脏检查,而更新始终将其数据保存到数据库,无论它是否脏。

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

答案 1 :(得分:11)

您在所有评估中都是完全正确的。你懂了。

对于您的第一个问题,如果我没记错,save专门插入一个。因此,再次调用save将导致db中的另一行。

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

答案 2 :(得分:7)

@Naliba对Update()方法给出了很好的答案。

以下图片中的休眠生命周期有助于了解方法。

enter image description here

示例:让我们看一下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);

以上student1处于分离状态,修改了分离的对象student1,现在如果我们调用update()方法,则hibernate将抛出错误。

在此session2中,我们现在调用session2.merge(s1); student2对象student1更改将合并并保存到数据库中。

答案 3 :(得分:4)

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

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

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

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

session.saveOrUpdate() - 此方法适用于新旧对象。如果object是new,它将像简单的save一样工作,或者如果object已经是持久的,它将像update一样工作。

session.lock() - 它仅用于对对象进行锁定,或者您可以说检查对象的版本。它不适用于更新对象。仅当您确定数据库中的对象状态未更改时,才应使用它来重新附加对象。否则,它可能会覆盖更改。 <邀请更多积分。

答案 4 :(得分:4)

update()用于分离的对象和瞬态对象。如果在持久对象上调用它将抛出NonUniqueObjectException,这将由merge()解决。

答案 5 :(得分:3)

遵循合并

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

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

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

答案 6 :(得分:0)

您应该在代码中应用save()和saveOrUpdate方法之间的差异,以获得最佳性能:

save()方法返回数据库生成的标识符。另一方面,saveOrUpdate()可以执行INSERT或UPDATE,具体取决于数据库中是否存在对象。 saveOrUpdate首先执行选择以确定是否需要执行插入或更新。因此,您应该在更新查询时使用saveOrUpdate。

save()和saveOrUpdate()方法的另一个关键区别是save()方法用于使瞬态对象成为持久状态,但saveOurUpdate()可以使瞬态(新对象)和分离(现有对象)对象进入持久状态。因此saveOrUpdate()通常用于将分离的对象重新附加到Session中。

来自帖子Difference between save and saveOrUpdate in Hibernate