Hibernate持续vs保存

时间:2013-11-15 05:20:07

标签: java hibernate

当我试图理解Hibernate Save和persist之间时,我遇到了这个解释:

  

persist()定义明确。它使瞬态实例持久化。   但是,它不保证标识符值   如果立即分配给持久化实例,则分配可能   在冲洗时发生。规范没有说明,这是问题所在   我有坚持()。

     

persist()还保证它不会执行INSERT语句   如果在事务边界之外调用它。这很有用   长时间运行的会话与扩展的会话/持久性   上下文。

     

需要像persist()这样的方法。

     

save()不保证相同,它返回一个标识符,如果   必须执行INSERT才能获得标识符(例如“身份”)   生成器,而不是“序列”),这个INSERT立即发生,无论如何   如果您在交易内部或外部。这不是一件好事   与长时间会话/持久性的长时间对话   上下文。

请你帮助我理解坚持的说法:

  

persist()还保证它不会执行INSERT语句   如果在事务边界之外调用它。这很有用   长时间运行的会话与扩展的会话/持久性   上下文。

这里有什么交易边界?什么是长期对话?什么是扩展的会话/持久化上下文意味着什么?

另外还有保存方法:

  

无论你是在里面还是在内,这种INSERT都会立即发生   在交易之外。这在长期运行中并不好   与扩展的会话/持久化上下文对话。

我知道如果我们在程序中使用save方法来保存对象,我们就不需要像session.beginTransaction()和session.getTransaction()。commt()这样的语句。如果声明在这里说同样的话,请告诉我。那么这对于长时间运行的对话有什么用呢?

我是新手,并且发现很难理解这些差异,请你帮我理解差异。

4 个答案:

答案 0 :(得分:4)

您的问题与Hibernate实现的Open Session in View模式有关。

这个想法是,您可能在Web应用程序中有一个原子工作单元,需要在整个特定进程中运行。想象一下在线订购食物。您在一个页面上登录,在下一页上选择披萨和浇头,在下一页上添加甜点,在下一页上添加饮料,然后在最后一页上付款。您希望整个过程成为一个单一的工作单元。

因此,Hibernate Session需要在该工作单元的开头打开并在结束时关闭 - 手动或通过某种容器管理。

在该对话期间调用persist不会导致任何数据插入,但会使分离的实体持久化。 Hibernate会“记录”所有插入内容,然后在会话结束时刷新它们。

同时save立即执行插入操作,并为您的实体提供数据库中的id。这在长时间运行的会话中并不好,因为您希望数据库操作是原子的 - 全部或全部。可能会发生类似数据的多次插入等奇怪的事情。

希望有所帮助。

答案 1 :(得分:1)

save()方法可以返回由hibernate生成的主键id值,我们可以通过

看到它
long s = session.save(k);

在同样的情况下,persist()永远不会给客户任何价值,希望你清楚。

所以persist()方法保证如果在事务边界之外调用它,它就不会执行INSERT语句,因为在持久化对象之后不需要获取id。

尽管save()方法不保证相同,因为它需要返回一个标识符(可能是主键id)。

必须执行INSERT以获取标识符(例如“identity”生成器),因此,无论您是在事务内部还是外部,此INSERT都会立即与save()一起发生。

答案 2 :(得分:1)

保存和持久方法之间的关键区别之一取决于ID生成策略。基本上save()方法会将值(id)返回给客户端并且persist()方法不会..

1)如果您让ORM引擎为您生成ID,在这种情况下您可以使用save()。原因很简单“Hibernate让您有机会了解它生成/使用的ID坚持你的对象“

2)如果您已经自己生成了id(分配了ID生成策略)并将其传递给ORM引擎以使用它来持久化您的对象。在这种情况下,persist()将是合适的。

点击here

正如我所说

  

“这取决于ID生成策略”

干杯!

答案 3 :(得分:0)

正如方法名称所示,hibernate save()可用于将实体保存到数据库。我们可以在事务外调用此方法。如果我们在没有事务的情况下使用它,并且我们在实体之间进行级联,那么除非我们刷新会话,否则只保存主实体

Hibernate persist类似于save(with transaction),它将实体对象添加到持久化上下文中,因此跟踪任何进一步的更改。如果在提交事务或刷新会话之前更改了对象属性,则它也将保存到数据库中。 此外,我们只能在事务的边界内使用persist()方法,因此它是安全的并且可以处理任何级联对象。 最后,persist不返回任何内容,因此我们需要使用持久化对象来获取生成的标识符值。