【发布时间】:2013-06-05 13:08:44
【问题描述】:
我想知道如何使用我的 Hibernate (4) 和 Oracle 设置减少 SQL 更新。
一个简单的例子可能是这样的:
打开一个会话/事务,使用 session.save() 创建一个新实体 Xyz,处理一些业务逻辑,对 Xyz 进行一些更改并调用 session.update(),然后让会话正常关闭并通过提交休眠到数据库。
提交时,Hibernate 会先插入,然后再进行更新——但它真正需要做的只是一次插入,但在本例中使用 Xyz 的 latest 属性。
有没有人对做这种事情有任何想法/模式?或者有什么办法可以改变 Hibernate 的行为吗?或者你对此有什么看法——它是一个完整的反模式吗?
我知道 Hibernate 足够聪明,可以忽略多个更新,当一个更新覆盖另一个更新时——那么为什么插入不相似呢?
这个小sn-p可以重现“问题”:
MyEntity e = new MyEntity("xxx");
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(e); e.setName("yyy");
session.getTransaction().commit();
session.close();
顺便说一句,我不用担心触发因素。
这个例子非常简单,性能问题可能看起来微不足道,但实际上我正在处理一个更复杂的对象(即多次插入和更新)和大量数据,因此避免更新会很好。
【问题讨论】:
-
您不能将保存移动到事务的末尾并在将更改保存到数据库之前将更改应用于实体吗?如果没有,请告诉我们是什么阻止了这种方法,以便我们制定解决方案。因为我不认为 Hibernate 内置了一个简单的解决方案(虽然不确定)。
-
这是一个解决方案,但问题是我正在使用各种其他有线服务,这些服务期望对象在会话中(他们从会话中读取对象)。而且它们在其他地方使用,因此重新分解它们比听起来要多。有没有办法可以将对象添加到会话中,并将其标记为持久性,但直到最后才调用 save() (即不会生成 INSERT)?
-
你是如何从其他服务的会话中获取实体的?
-
我想您将不得不扩展您的示例,以便我掌握它。 ^^" 但是如果你使用不同的'事务'和'session.get'之类的东西,就没有办法解决这个问题,因为几乎所有的Hibernate实体获取方法都旨在获取持久实体。如果是这样的话,我担心会有这里没有快速获胜。唯一的机会可能是以某种方式滥用缓存(使用内置方法或可能使用反射)并防止刷新。但只考虑这一点似乎是错误的。xD
-
您好,感谢您的意见。根据传递给实体的 id 在各个点重新读取实体——这是在实体实例化时创建的!实际上,实体刚刚被“保存”并且将在缓存中,而不是在数据库中,因为事务还没有结束。这都是一笔大交易。将外部包装器视为创建实体的事物,它为某些可能更改实体属性的业务逻辑调用其他服务。我同意这里也可能没有速赢。
标签: hibernate session optimization insert save