2012-02-24 108 views
5

我讀Eric Evans的書約DDD和我有以下報價的問題。當你不應該使用這些屬性時,你如何制定equals()方法?我正在使用JPA,並且我有一個唯一的id屬性,但是隻有在實際持久化後才能設置。所以你會怎麼做?我已經實現了基於屬性的equals方法,我明白你爲什麼不應該這樣做,因爲它在我的項目中失敗了。在實體領域驅動設計

節約實體:

當對象是由它的身份來區分,而不是它的 的屬性,使這種初級其在模型定義。保持類別定義簡單並集中於生命週期連續性和 身份。定義一種區分每個對象的方法,而不管其形式或歷史如何。警惕需要按屬性匹配 對象的需求。定義一個操作,保證 爲每個對象產生一個唯一的結果,可能通過附加一個保證唯一的 符號。的識別這個裝置可以 來自外部,或者它可以是通過 和爲系統創建一個任意的標識符,但它必須對應於身份模型中的 區別。該模型必須定義什麼意思是 同樣的事情。

http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215

+0

可能的複製,見http://stackoverflow.com/questions/5031614/the-jpa-hashcode-equals-dilemma – MRalwasser 2012-02-24 13:27:51

+0

的ID正常工作對我來說:http://stackoverflow.com/questions/7579404/using-auto-generated-id-of-hibenate-entity-object-in-the-the-the-the-the-the-and-hashcode-met – NimChimpsky 2012-02-24 14:54:06

回答

1

夫婦辦法可能:

  • 使用業務鍵值。這是最符合「DDD標準」的方法。仔細查看域名和業務要求。例如,您的企業如何識別客戶?他們是否使用社會安全號碼或電話號碼?如果基於紙張(無電腦),您的企業如何解決這個問題?如果沒有自然的商業密鑰,請創建代理。選擇最終的商業密鑰並在equals()中使用它。 DDD書中有一節專門討論這個特定問題。

  • 對於案件時,有沒有自然業務鍵,您可以生成UUID。這在分佈式系統中也有優勢,在這種情況下,您不需要依賴像數據庫這樣的集中式(並且可能不可用)資源來生成新的ID。

  • 還有一個選項可以僅僅依靠默認的equals()實體類。它會比較兩個內存位置,並且在大多數情況下都足夠了,因爲Unit Of Work(Hibernate Session)持有所有實體(此ORM模式稱爲Identity Map)。這是不可靠的,因爲如果你使用不侷限於一個Hibernate的Session的範圍內實體(思線程,分離的實體等)

有趣的是,「官方」 DDD示例使用一個非常這將打破輕量級框架,其中每一個實體類是從Entity接口派生與一種方法:

boolean sameIdentityAs(T other) 
// Entities compare by identity, not by attributes. 
+0

假設實體是問題。我會用什麼?直到現在,我依靠生成的ID。 – LuckyLuke 2012-02-24 13:31:37

+0

取決於你的域名,可能是問題本身的文本(在這種情況下,它可能是Value not Entity),但更可能是問題編號。真的取決於你的域名。 – Dmitry 2012-02-24 14:04:00

1

如果對象是不持久的呢,那麼有沒有在根據其屬性比較兩個對象的任何傷害?

我不知道爲什麼這個失敗的項目,但在我的經驗,基於屬性幾乎總是比較光滑的斜坡,如果你的屬性並不是最終的。這意味着,現在有兩個相同的對象,在某個時間後可能不相同。這真是太糟了。

鑑於大多數Java類與他們一起存取寫,等於比較屬性被認爲是一個壞主意。

不過,我可能會先檢查,看看是否ID字段不爲空。如果它爲空,我會迴歸屬性比較。如果它不是空的,那就使用它,不要做任何其他事情。這有意義嗎?

+2

這是一件很危險的事情。如果您在分配其ID之前將對象存儲在HashSet中,則HashSet將被損壞。 – 2012-02-25 08:14:13

+0

當然。但是,那麼,我會假設你會堅持這個對象來獲得這個id。在這種情況下,我通常更喜歡獲取返回的持久化對象並使用它。基本上,不要改變在平等檢查中使用的對象的狀態。 – Pavan 2012-02-25 11:15:28

+0

如果您根據其屬性比較對象,那麼它的行爲就像是一個Value Object而非一個Entity。值對象和實體在DDD中具有完全不同的語義,因此您不應將實體相等性置於屬性上。 – 2014-03-11 01:43:45

1

鑑於Person類具有屬性namesurname。當21歲的人改名時,仍然是同一個人(等於true)? 如果你寫出等於基礎的屬性,那麼它不會是同一個人,所以在我看來,最好的方法是在他們的業務標識符(在整個實體生命週期中唯一且不可變)測試實體基礎的平等。

0

另一種解決方案可能是在您的實體中使用UUID字段。

在這種情況下,您可以使用UUID作爲主鍵或僅用於等於。

@Entity 
public class YourEntity{ 

    @Id 
    private String uuid = UUID.randomUUID().toString(); 

    // getter only... 

}