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

Xiè*_*léi 59 java orm identity entity-relationship hibernate

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

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

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

如果Hibernate不会使用hashCode()/ equals()来检查脏状态,我想我不应该使用equals()/ hashCode()作为实体对象(而不是值对象),但我也担心如果相同的operator(==)是不够的.

所以,问题是:

  1. Hibernate如何知道对象的属性是否发生了变化?

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

    并且,

  3. hashCode()/ equals()只有这个id领域就足够了?

Ant*_*nio 94

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

来源:书中的Hibernate in Action(附录B:ORM实施策略)

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

  • 我认为问题的一部分是如何进行比较?我的意思是==检查存储快照的每个属性?或者是其他东西? (3认同)

Vla*_*cea 18

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

您可以在下图中更好地可视化此过程:

默认自动脏检查


use*_*246 7

Hibernate进行逐字段检查以确定实体的肮脏程度.

所以hashCode/equals根本没有进入图片.

实际上,Hibernate完成的逐字段脏检查在性能方面可能非常昂贵.

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

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