2011-03-11 114 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