2011-03-11 34 views
46

对原始类使用某种字节码修改吗?Hibernate如何检测实体对象的脏状态?

或者,也许Hibernate通过比较给定的对象与以前的持久版本来获取脏状态?

我在hashCode()equals()复杂对象的方法有问题。如果对象具有集合成员,那么计算哈希代码的速度会很慢,并且循环引用也是一个问题。

如果Hibernate不会使用hashCode()/equals()检查脏的状态,我想我不应该使用equals()/hashCode()对实体对象(不是值对象),但我也害怕,如果同一个运营商(== ) 是不足够的。

所以,问题是:

  1. 如何休眠知道,如果一个对象的属性发生变化?

  2. 您是否建议覆盖复杂对象的hashCode()/equals()方法?如果它们包含循环引用呢?

    而且,也

  3. hashCode()/equals()只用id场够吗?

回答

85

休眠使用称为检查策略,这基本上是这样的:当一个对象从数据库加载的它的快照被保持在存储器中。当会话刷新时,Hibernate将存储的快照与当前状态进行比较。如果它们不同,则该对象被标记为脏并且合适的SQL命令被入队。如果对象仍然是短暂的,那么它总是很脏。

来源:本书在行动休眠(附录B:ORM的实现策略)

然而它注意到重要的是Hibernate的脏检查是独立的方法等于/ hascode。 Hibernate根本没有查看这些方法(除了使用java.util.Set之外,但这与脏检查无关,仅适用于Collections API)。前面提到的状态快照与一组值类似。将这个框架的核心部分留在开发者手中是一个非常糟糕的决定(老实说,开发人员不应该关心肮脏检查)。不用说,equals/hascode可以根据您的需要以多种方式实现。我建议你阅读引用的书,那里的作者讨论等于/ hascode实施策略。非常有见地的阅读。

+2

我认为问题的一个部分是如何进行比较?我的意思是==检查存储快照的每个属性?或者是其他东西? – 2015-05-11 07:59:59

6

Hibernate进行逐字段检查以确定实体的不洁性。

所以hashCode/equals根本不会进入图片。实际上,由Hibernate完成的逐字段脏检查在性能方面可能相当昂贵。

因此它提供像Strategy或Interceptor.findDirty()这样的接口来处理相同的问题。

下面的帖子中更详细地解释了这个(非常久远的一些想法应用优化它完全):http://prismoskills.appspot.com/lessons/Hibernate/Chapter_20_-_Dirty_checking.jsp

+0

在逐字段检查过程中,如果字段的值不相同(使用==检查返回false),则使用equals检查值是否已更改。请参阅脏检查方法调用链中使用的org.hibernate.internal.util.compare.EqualsHelper.equals(Object,Object)。 – Popeye 2016-11-01 05:12:03

-2

它在加载/通过ID得到实体对象,然后通过setter方法和设置其新的字段值simple--关闭会话而不调用update()方法。然后休眠自动更新表中更改的值,而不会影响其他字段。 ,同时实体对象处于脏状态

+0

这不是OP问题的答案 – MariuszS 2017-07-28 08:53:02