Hibernate如何检测实体对象的脏状态?

它是使用某种字节代码修改原始类?

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

我遇到了复杂对象的hashCode()equals()方法的问题。 如果对象具有集合成员,我觉得计算哈希代码会很慢,而循环引用也是一个问题。

如果Hibernate不会使用hashCode() / equals()来检查脏状态,我想我不应该使用equals() / hashCode()作为实体对象(不是value对象),但是我也害怕如果相同的运算符( == )是不够的。

所以,问题是:

  1. Hibernate如何知道对象的属性是否改变?

  2. 你build议覆盖hashCode() /等equals()方法复杂的对象吗? 如果它们包含循环引用呢?

    并且,

  3. 只有id域的hashCode() / equals()会不够?

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

资料来源:“Hibernate in Action”(附录B:ORM实施策略)

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

Hibernate默认的脏检查机制将匹配所有当前连接实体的所有映射属性与其初始加载时间值。

您可以在下图中更好地看到这个过程:

默认自动脏检查

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

所以hashCode / equals根本不会进入图片。

实际上,由Hibernate完成的逐字段脏检查在性能方面可能是相当昂贵的。

所以它提供了像Strategy或Interceptor.findDirty()这样的接口来处理。

以下文章更详细地解释了这一点(以及应用程序的一些想法来完全优化 ): http : //prismoskills.appspot.com/lessons/Hibernate/Chapter_20_-_Dirty_checking.jsp

很简单 – 当你通过id加载/获取实体对象,然后通过setter方法设置新的字段值。 然后hibernate自动更新表中更改的值,而不会影响其他字段。 同时实体对象处于肮脏状态