我是Hibernate的新手,上周经历了Hibernate教程。我对Session类中的方法save,update,saveOrUpdate和merge有一些疑问。这些是:
保存方法:它用于在数据存储区中插入新创建的对象。 (基本上标识符值为0)。就像我创建一个新客户并调用保存操作一样,它会将其保留在数据存储区中并生成标识符。
这是对的吗?如果我们在已经持久的对象上调用save,不确定会发生什么?
更新方法:它用于更新数据存储区中已经存在的对象。(基本上,标识符值将是一些非零值)。就像我在更新某个字段值后加载新客户并调用更新操作一样,它会在数据存储区中更新它。
根据我的理解,它应该失败并出现一些异常,因为根据API更新是针对分离对象的。它是否正确?如果是,我们应该调用什么来更新同一会话中的对象(我的意思是如果对象没有分离)。另一点是:如果我们在新创建的对象上调用update,会发生什么?
saveOrUpdate方法:它将基于未保存值检查调用上述任何一个(它必须根据标识符零或非零值进行调用,对吧?)所以如果我们有持久客户对象,我们更新他的姓氏并创建一个新帐户,然后saveOrUpdate将负责处理。
我理解正确吗?
合并方法:它会像更新一样,但是如果会话中已经有一个具有相同标识符的持久对象,它将更新持久对象中的分离对象值并保存它。
但是如果当前没有与会话关联的持久化实例,这将从数据存储区加载持久对象,然后更新已加载的持久对象中的分离对象的值,然后更新它。
我也明白了吗?
答案 0 :(得分:30)
你有大多数事情是正确的,但更新与你描述它的方式略有不同。如果对象在会话中(即持久),则完全不需要更新。当刷新会话时,Hibernate会处理对会话中对象的任何更改。调用它们的更新将不会做任何事情(并且可能会导致性能损失;我不确定)。
更新旨在在分离的对象上调用,即那些现在在加载的会话之外的对象。@ hvgotcodes解释似乎不正确,因为只有当对象不时才应调用更新em>在会话中。如果对象的实例已在会话中,则更新可能会失败。在这种情况下应该使用合并。它将分离对象的更改与会话中的对象(如果存在)合并。如果会话中没有对象,它将创建一个新对象。
通常你可以避免调用更新/合并,但如果最终不得不调用一个,则merge会处理更广泛的情况。我的理解是,使用更新的唯一原因是为了获得更好的性能,假设您知道它不会出错。
This thread对其他一些hibernate方法也有很好的总结。
编辑:我只是认为我应该说合并和更新之间的差异比我原先说的要多。 Update将给定实体修改为持久性,而merge则返回新的持久性实体。对于合并,你应该扔掉旧的对象。另一个区别是合并在决定是否写入数据之前通过从DB中选择进行脏检查,而更新始终将其数据保存到数据库,无论它是否脏。
可能还有其他一些小差异。通过记录生成的SQL来测试Hibernate行为总是好的,因为行为并不总是与文档匹配,至少在我的经验中是这样。
答案 1 :(得分:11)
您在所有评估中都是完全正确的。你懂了。
对于您的第一个问题,如果我没记错,save
专门插入一个。因此,再次调用save将导致db中的另一行。
对于第二个问题,update
更新会话中的对象。因此,如果对象在会话中,它将更新。如果对象不在会话中,则应调用merge。我认为为分离的实例调用update
将导致异常。
答案 2 :(得分:7)
@Naliba对Update()方法给出了很好的答案。
以下图片中的休眠生命周期有助于了解方法。
示例:让我们看一下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)
遵循合并
合并有智慧。它在进行实际合并之前有很多预检(如果需要)其中session.update
session.merge比更新
贵答案 6 :(得分:0)
您应该在代码中应用save()和saveOrUpdate方法之间的差异,以获得最佳性能:
save()方法返回数据库生成的标识符。另一方面,saveOrUpdate()可以执行INSERT或UPDATE,具体取决于数据库中是否存在对象。 saveOrUpdate首先执行选择以确定是否需要执行插入或更新。因此,您应该在更新查询时使用saveOrUpdate。
save()和saveOrUpdate()方法的另一个关键区别是save()方法用于使瞬态对象成为持久状态,但saveOurUpdate()可以使瞬态(新对象)和分离(现有对象)对象进入持久状态。因此saveOrUpdate()通常用于将分离的对象重新附加到Session中。