簡體   English   中英

應該在equals / hashCode / toString中使用@Transient屬性嗎?

[英]Should @Transient property be used in equals/hashCode/toString?

我有JPA實體,其中一些屬性使用@Transient注釋。

我應該在equals/hashCode/toString方法中使用這些屬性嗎?

我的第一個想法是不,但我不知道為什么。

  • 提示?
  • 想法?
  • 解釋嗎?

toString()情況不同,你可以用toString()做任何你想要的事情,所以我只會覆蓋equals() (和hashCode() )。

首先,規則: 如果要將對象存儲在ListMapSet ,則需要實現equalshashCode以便它們遵守文檔中指定的標准合同

現在,如何實現equals()hashCode() 一個“自然”的想法是使用映射為Id的屬性作為equals()

public class User {
    ...
    public boolean equals(Object other) {
        if (this==other) return true;
        if (id==null) return false;
        if ( !(other instanceof User) ) return false;
        final User that = (User) other;
        return this.id.equals( that.getId() );
    }
    public int hashCode() {
        return id==null ? System.identityHashCode(this) : id.hashCode();
  }
}

不幸的是,這個解決方案有一個主要問題 :當使用生成的標識符時,在實體變為持久化之前不會分配值,因此如果在保存之前將一個瞬態實體添加到Set ,則其哈希代碼將在Set更改打破了Set的合同。

因此,推薦的方法是使用屬於業務鍵的屬性,即對於具有相同數據庫標識的每個實例唯一的屬性組合。 例如,對於User類,這可以是用戶名:

public class User {
    ...
    public boolean equals(Object other) {
        if (this==other) return true;
        if ( !(other instanceof User) ) return false;
        final User that = (User) other;
        return this.username.equals( that.getUsername() );
    }
    public int hashCode() {
        return username.hashCode();
  }
}

Hibernate參考文檔總結如下:

永遠不要使用數據庫標識符來實現相等性;使用業務鍵,唯一的,通常是不可變的屬性的組合 。如果瞬態對象是持久的,數據庫標識符將會改變。如果瞬態實例(通常與分離的實例一起)是保存在Set ,更改hashcode會破壞Set的約定。業務鍵的屬性不必像數據庫主鍵一樣穩定,只要對象在同一個Set中,就必須保證穩定性。 - 12.1.3。 考慮對象身份

建議您使用Business鍵相等來實現equals()hashCode() 。業務鍵相等性意味着equals()方法僅比較構成業務鍵的屬性。它是一個用於標識我們的實例的鍵。現實世界(自然候選鍵)“ - 4.3。 實現equals()和hashCode()

那么,回到最初的問題:

  • 如果可能,請使用業務密鑰。 @Transient屬性很可能不屬於這樣一個鍵。
  • 如果不可能,請使用標識符屬性,但請確保在將實體添加到ListMapSet之前獲取指定的值。

也可以看看

異常可能來自於讓它是transient ,同時你提供writeObject()readObject()處理它。

我所知道的@Transienttransient的兩個典型用法是將它們用於無法序列化/持久化的東西(例如遠程資源句柄 )或可以從其他人重建的計算屬性。

對於計算數據 ,在等式關系( equals/hashCode )中使用它們是沒有意義的,因為它將是多余的。 該值是從已在相等中使用的其他值計算出來的。 然而,在toString打印它們仍然是有意義的(例如,基本價格和比率用於計算實際價格)。

對於不可序列化/可持久化的數據 ,它取決於。 我可以想象一個不可序列化的資源的句柄,但你仍然可以比較句柄所代表的資源名稱。 對於toString ,也許打印句柄資源名稱很有用。

這是我的2美分,但如果你解釋你對@Transient的特殊用法,有人可以提供更好的建議。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM