保存,更新,saveOrUpdate,合并方法在Session中的区别?

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

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

    它是否正确? 如果我们调用保存已经持久化的对象不知道会发生什么?

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

    根据我的理解,它应该失败,并有一些例外,因为每个API更新是针对分离的对象。 它是否正确? 如果是的话,我们应该调用什么来更新在同一个会话中的对象(我的意思是如果对象不分离)。 另一点是:如果我们调用更新新创build的对象会发生什么?

  • saveOrUpdate方法:它会基于未保存的值检查(它必须根据标识符为零或非零值进行操作),因此如果我们有持续的客户对象,并更新其姓氏并创build一个新的帐户,然后saveOrUpdate将照顾它。

    我理解正确吗?

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

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

    我也得到了吗?

你的评估完全正确。 你懂了。

对于你的第一个问题,如果我记得正确, save具体做一个插入。 所以再次调用save会导致数据库中的另一行。

对于第二个问题, update会话中的更新对象。 所以如果对象在会话中会更新。 如果对象不在会话中,则应调用合并。 我相信调用update的分离实例将导致一个exception。

你有很多东西是正确的,但是更新与你描述它的方式有点不同。 如果一个对象在会话中(即持续),更新是完全不必要的。 当会话刷新时,Hibernate处理对会话中对象的任何更改。 调用它们的更新无效(可能会导致性能损失;我不确定)。

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

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

这个线程也有一些其他hibernate方法的相当不错的总结。

编辑:我只是觉得我应该说,合并和更新之间有更多的差异比我原来说的。 更新修改给定的实体是持久的,而合并返回一个新的持久实体。 合并,你应该扔掉旧的对象。 另一个区别是,合并在决定是否写入其数据之前,通过从数据库中进行select来进行脏检查,而更新总是将数据保存到数据库中,而不pipe数据是否脏。

可能还有其他的小差异。 通过logging生成的SQL来testingHibernate行为总是好的,因为行为并不总是与文档相匹配,至less在我的经验中。

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

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

session.save() – 它可以用来保存一个新的对象。 它返回可序列标识。

session.persist() – 和save()一样,但是是void方法,不返回任何东西。

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

session.lock() – 仅用于对对象的locking,或者可以说检查对象的版本。 这并不意味着更新对象。 只有在确定数据库中的对象状态没有被更改的情况下,才应使用它重新挂接对象。 否则,它可能会覆盖更改。 <邀请更多关于此的点。

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

在下面的图像的Hibernate生命周期有助于得到一个方法上方的想法。

在这里输入图像说明

例子:让我们看看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变化将被合并并保存到数据库中。

update()用于分离对象和瞬态对象。 如果在持久化对象上调用它将抛出NonUniqueObbjectException,这将通过merge()来解决。

合并以下

合并有智慧。 它在实际合并之前有很多预先检查(如果需要的话)

  1. 如果Object是暂时的,它只是简单地触发INSERT查询使对象持久化(附加到会话)
  2. 如果Object被分离,则触发select查询来检查数据是否被修改,如果被修改,则触发UPDATE查询,否则忽略合并任务。

在那里作为session.update

  1. 抛出exception如果对象是瞬态的。
  2. 如果Object是分离的,它只是简单地触发UPDATE查询而不pipe对象的数据变化。

session.merge比更新要贵

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

save()方法返回数据库生成的标识符。 另一方面,saveOrUpdate()可以根据数据库中是否存在对象来执行INSERT或UPDATE。 saveOrUpdate首先进行select,以确定是否需要执行插入或更新。 所以你应该在大小写更新查询中使用saveOrUpdate。

save()和saveOrUpdate()方法之间的另一个关键区别是save()方法用于使暂存对象处于持久状态,但saveUpdate()可以使临时(新对象)和分离(现有对象)对象都处于持久状态。 所以saveOrUpdate()通常用来将分离的对象重新附加到Session中。

从Hibernate的save和saveOrUpdate之间的差异