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

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

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

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

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

所以,问题是:

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

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

    而且,

  3. /只有字段就足够了吗?hashCode()equals()id


答案 1

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

资料来源:《冬眠在行动》一书(附录B:ORM实施策略)

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


答案 2

休眠默认脏检查机制将根据其初始加载时间值匹配所有当前附加实体的所有映射属性。

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

Default automatic dirty checking


推荐