6

我想知道如何使用我的 Hibernate (4) 和 Oracle 设置来减少 SQL 更新。

一个简单的例子可能是这样的:

打开一个会话/事务,使用 session.save() 创建一个新实体 Xyz,处理一些业务逻辑,对 Xyz 进行一些更改并调用 session.update(),然后让会话正常关闭并休眠并提交到 DB。

提交时,Hibernate 会先插入,然后再进行更新——但在本例中,它真正需要做的只是一次插入,但要使用 Xyz 的最新属性。

有没有人有任何想法/模式来做这种事情?或者有什么办法可以改变 Hibernate 的行为吗?或者你对此有什么看法——它是一个完整的反模式吗?

我知道 Hibernate 足够聪明,可以忽略多个更新,当一个更新只是覆盖另一个更新时——那么为什么插入不相似呢?

这个小片段可以重现“问题”:

MyEntity e = new MyEntity("xxx"); 
Session session = sessionFactory.openSession(); 
session.beginTransaction();
session.save(e); e.setName("yyy"); 
session.getTransaction().commit(); 
session.close();

顺便说一句,我不用担心触发因素。

这个例子非常简单,性能问题可能看起来微不足道,但实际上我正在处理一个更复杂的对象(即多次插入和更新)和大量数据,因此避免更新会很好。

4

1 回答 1

1

有没有办法可以将对象添加到会话中,并将其标记为持久性,但直到最后才调用 save() (即不会生成 INSERT)?

如果您想推迟执行直到会话刷新和/或事务关闭,请考虑使用重构Session.persist(Object)Session.save(Object)INSERT

JBoss Hibernate 社区文档的第 10.2 节:

您还可以使用 EJB3 早期草案中定义的语义来使用 persist() 代替 save()。

  • persist()使瞬态实例持久化。但是,它不能保证标识符值将立即分配给持久实例,分配可能发生在刷新时间。 还保证如果在事务边界之外调用persist()它不会执行语句。INSERT这在具有扩展会话/持久性上下文的长时间运行的对话中很有用。
  • save()确实保证返回一个标识符。如果INSERT必须执行 an 来获取标识符(例如“身份”生成器,而不是“序列”),这INSERT会立即发生,无论您是在事务内部还是外部。这在具有扩展会话/持久性上下文的长期对话中是有问题的。

另一个有用的参考可以在这篇博客文章“把它放在一起”部分顶部的方法到场景网格的左上角单元格中找到,它描述了从未持久化的对象的行为,如下所示:persist()

  1. 对象作为新实体添加到持久性上下文
  2. flush()在/处插入数据库的新实体commit()
于 2013-07-04T06:05:44.477 回答