Hibernate有一些方法,以这种或那种方式,获取对象并将其放入数据库.它们之间有什么区别,什么时候使用哪个,为什么不存在一个知道何时使用什么的智能方法?
到目前为止我发现的方法是:
save()
update()
saveOrUpdate()
saveOrUpdateCopy()
merge()
persist()
Lee Theobald.. 117
这是我对这些方法的理解.主要是这些是基于API,但我没有在实践中使用所有这些.
saveOrUpdate 根据某些检查调用保存或更新.例如,如果不存在标识符,则调用save.否则调用更新.
保存 持有实体.如果不存在标识符,将分配标识符.如果有的话,它实质上是在进行更新.返回生成的实体ID.
update 尝试使用现有标识符持久保存实体.如果不存在标识符,我认为会抛出异常.
saveOrUpdateCopy 这是不推荐使用的,不应再使用.而是......
合并 现在这是我的知识开始蹒跚的地方.这里重要的是瞬态,分离和持久实体之间的区别.有关对象状态的更多信息,请查看此处.通过保存和更新,您将处理持久对象.它们链接到一个Session,因此Hibernate知道发生了什么变化.但是当你有一个瞬态对象时,就没有涉及会话.在这些情况下,您需要使用merge进行更新并保留以进行保存.
persist 如上所述,这用于瞬态对象.它不会返回生成的ID.
这是我对这些方法的理解.主要是这些是基于API,但我没有在实践中使用所有这些.
saveOrUpdate 根据某些检查调用保存或更新.例如,如果不存在标识符,则调用save.否则调用更新.
保存 持有实体.如果不存在标识符,将分配标识符.如果有的话,它实质上是在进行更新.返回生成的实体ID.
update 尝试使用现有标识符持久保存实体.如果不存在标识符,我认为会抛出异常.
saveOrUpdateCopy 这是不推荐使用的,不应再使用.而是......
合并 现在这是我的知识开始蹒跚的地方.这里重要的是瞬态,分离和持久实体之间的区别.有关对象状态的更多信息,请查看此处.通过保存和更新,您将处理持久对象.它们链接到一个Session,因此Hibernate知道发生了什么变化.但是当你有一个瞬态对象时,就没有涉及会话.在这些情况下,您需要使用merge进行更新并保留以进行保存.
persist 如上所述,这用于瞬态对象.它不会返回生成的ID.
????????????????????????????????????????????????????????????????????????????????? ? METHOD ? TRANSIENT ? DETACHED ? ????????????????????????????????????????????????????????????????????????????????? ? ? sets id if doesn't ? sets new id even if object ? ? save() ? exist, persists to db, ? already has it, persists ? ? ? returns attached object ? to DB, returns attached object ? ????????????????????????????????????????????????????????????????????????????????? ? ? sets id on object ? throws ? ? persist() ? persists object to DB ? PersistenceException ? ? ? ? ? ????????????????????????????????????????????????????????????????????????????????? ? ? ? ? ? update() ? Exception ? persists and reattaches ? ? ? ? ? ????????????????????????????????????????????????????????????????????????????????? ? ? copy the state of object in ? copy the state of obj in ? ? merge() ? DB, doesn't attach it, ? DB, doesn't attach it, ? ? ? returns attached object ? returns attached object ? ????????????????????????????????????????????????????????????????????????????????? ? ? ? ? ?saveOrUpdate()? as save() ? as update() ? ? ? ? ? ?????????????????????????????????????????????????????????????????????????????????
有关持久化和保存之间细微差别的解释,请参阅Hibernate论坛.看起来不同的是INSERT语句最终执行的时间.由于save确实返回了标识符,因此无论事务的状态如何(通常都是坏事),INSERT语句都必须立即执行.Persist不会为了分配标识符而在当前运行的事务之外执行任何语句.保存/保持两者都可以处理瞬态实例,即尚未分配标识符的实例,因此不会保存在数据库中.
更新和合并都适用于分离的实例,即在DB中具有相应条目但当前未附加到会话(或由其管理)的实例.它们之间的区别是传递给函数的实例会发生什么.update尝试重新附加实例,这意味着现在可能没有附加到Session的持久实体的其他实例,否则抛出异常.但是,merge只是将所有值复制到Session中的持久化实例(如果当前未加载,将加载它).输入对象不会更改.因此,merge比更新更通用,但可能会使用更多资源.
此链接以良好的方式解释:
http://www.stevideter.com/2008/12/07/saveorupdate-versus-merge-in-hibernate/
我们都遇到了很少遇到的问题,当我们再次看到它们时,我们知道我们已经解决了这个问题,但却记不起来了.
在Hibernate中使用Session.saveOrUpdate()时抛出的NonUniqueObjectException是我的一个.我将为复杂的应用程序添加新功能.我所有的单元测试都运行良好.然后在测试UI时,尝试保存一个对象,我开始得到一个异常,消息"具有相同标识符值的另一个对象已经与会话相关联."这是来自Java Persistence with Hibernate的一些示例代码.
Session session = sessionFactory1.openSession(); Transaction tx = session.beginTransaction(); Item item = (Item) session.get(Item.class, new Long(1234)); tx.commit(); session.close(); // end of first session, item is detached item.getId(); // The database identity is "1234" item.setDescription("my new description"); Session session2 = sessionFactory.openSession(); Transaction tx2 = session2.beginTransaction(); Item item2 = (Item) session2.get(Item.class, new Long(1234)); session2.update(item); // Throws NonUniqueObjectException tx2.commit(); session2.close();
要了解此异常的原因,了解分离的对象以及在分离的对象上调用saveOrUpdate()(或只是update())时会发生什么很重要.
当我们关闭一个单独的Hibernate Session时,我们正在处理的持久对象被分离.这意味着数据仍然在应用程序的内存中,但Hibernate不再负责跟踪对象的更改.
如果我们然后修改我们的分离对象并想要更新它,我们必须重新附加该对象.在重新附加过程中,Hibernate将检查是否存在同一对象的任何其他副本.如果它找到了,它必须告诉我们它不知道"真正的"副本是什么了.也许对我们希望保存的其他副本进行了其他更改,但Hibernate不了解它们,因为它当时没有管理它们.
Hibernate不是保存可能不好的数据,而是通过NonUniqueObjectException告诉我们这个问题.
那么我们该怎么办呢?在Hibernate 3中,我们有merge()(在Hibernate 2中,使用saveOrUpdateCopy()).此方法将强制Hibernate将来自其他分离实例的任何更改复制到要保存的实例上,从而在保存之前合并内存中的所有更改.
Session session = sessionFactory1.openSession(); Transaction tx = session.beginTransaction(); Item item = (Item) session.get(Item.class, new Long(1234)); tx.commit(); session.close(); // end of first session, item is detached item.getId(); // The database identity is "1234" item.setDescription("my new description"); Session session2 = sessionFactory.openSession(); Transaction tx2 = session2.beginTransaction(); Item item2 = (Item) session2.get(Item.class, new Long(1234)); Item item3 = session2.merge(item); // Success! tx2.commit(); session2.close();
重要的是要注意merge返回对实例的新更新版本的引用.它不会将项目重新附加到会话.如果你测试实例相等(item == item3),你会发现在这种情况下它返回false.从这一点开始,您可能希望使用item3.
值得注意的是,Java Persistence API(JPA)没有分离和重新附加对象的概念,并使用EntityManager.persist()和EntityManager.merge().
我发现在使用Hibernate时,saveOrUpdate()通常足以满足我的需求.当我拥有可以引用相同类型对象的对象时,我通常只需要使用merge.最近,异常的原因在于代码验证引用不是递归的.作为验证的一部分,我正在将同一个对象加载到我的会话中,从而导致错误.
你在哪里遇到过这个问题?合并是否适用于您,或者您是否需要其他解决方案?您是否希望始终使用合并,或者仅在特定情况下根据需要使用合并
实际上,hibernate save()
和persist()
方法之间的区别取决于我们正在使用的生成器类.
如果我们的生成器类被分配,那么save()
和persist(
方法之间没有区别.因为生成器'已分配'意味着,作为程序员,我们需要将主键值保存在数据库中[希望您知道这个生成器概念]如果不是指定的生成器类,假设我们的生成器类名称是递增均值hibernate it self会将主键id值分配到数据库中[除了分配的生成器,hibernate只用于照顾主键id值记住],所以在这种情况下如果我们调用save()
或者persist()
方法那么它会将记录插入正常数据库但是听到的是, save()
方法可以返回由hibernate生成的主键id值,我们可以看到它
long s = session.save(k);
在同样的情况下,persist()
永远不会给客户任何价值.
我找到了一个很好的例子,显示了所有hibernate保存方法之间的差异:
http://www.journaldev.com/3481/hibernate-session-merge-vs-update-save-saveorupdate-persist-example
总之,根据以上链接:
保存()
我们可以在事务外调用此方法.如果我们在没有事务的情况下使用它,并且我们在实体之间进行级联,那么除非我们刷新会话,否则只保存主实体.
因此,如果从主对象映射了其他对象,则会在提交事务或刷新会话时保存它们.
坚持()
它类似于在事务中使用save(),因此它是安全的并且可以处理任何级联对象.
saveOrUpdate()方法
可以在有或没有事务的情况下使用,就像save()一样,如果它在没有事务的情况下使用,映射的实体将不会被保存为un; ess我们刷新会话.
根据提供的数据生成插入或更新查询的结果.如果数据存在于数据库中,则执行更新查询.
更新()
当我们知道我们只更新实体信息时,应该使用Hibernate更新.此操作将实体对象添加到持久上下文,并在提交事务时跟踪和保存进一步的更改.
因此,即使在调用update之后,如果我们在实体中设置任何值,它们将在事务提交时更新.
合并()
Hibernate merge可用于更新现有值,但此方法从传递的实体对象创建副本并返回它.返回的对象是持久化上下文的一部分,并跟踪任何更改,不跟踪传递的对象.这是与所有其他方法的merge()的主要区别.
另外,对于所有这些的实际例子,请参考我上面提到的链接,它显示了所有这些不同方法的示例.