亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何使用@NaturalId 正確覆蓋 Hibernate 實體的等于

如何使用@NaturalId 正確覆蓋 Hibernate 實體的等于

慕工程0101907 2022-07-20 10:58:00
已經多次討論過如何為實體重新定義 equals/hashCode。我的問題是關于是否需要使用 equals 中的所有字段。考慮兩種情況。當我們將所有字段用于等于時:@Entitypublic class Book {    @Id    @Column    @GeneratedValue(strategy = GenerationType.IDENTITY)    private Long id;    @NaturalId    @Column(name = "isbn", nullable = false, unique = true)    private String isbn;    @Column    private String name;    private Book() {    }    public Book(String isbn) {        this.isbn = isbn;    }    @Override    public boolean equals(Object o) {        if (this == o) return true;        if (o == null || getClass() != o.getClass()) return false;        Book book = (Book) o;        return Objects.equals(id, book.id) &&                Objects.equals(isbn, book.isbn) &&                Objects.equals(name, book.name);    }    @Override    public int hashCode() {        return Objects.hash(isbn);    }}并測試:public class BookTest1 {    @PersistenceContext    protected EntityManager em;    @Test    public void fromTransientToManageSameEntity() {        Book book1 = new Book("4567-5445-5434-3212");        Book book2 = new Book("4567-5445-5434-3212");        em.persist(book2);        flushAndClean();        assertThat(book1, is(not((equalTo(book2))))); // not equals    }}正如我們所看到的,當將實體從瞬態轉換為管理狀態時 - 相同的實體將不相等。另一種情況是當我們只使用等于@NaturalId 時:@Overridepublic boolean equals(Object o) {    if (this == o) return true;    if (o == null || getClass() != o.getClass()) return false;    Book book = (Book) o;    return Objects.equals(isbn, book.isbn);}并測試:public class BookTest2 {    @PersistenceContext    protected EntityManager em;    @Test    public void fromTransientToManageSameEntity() {        Book book1 = new Book("4567-5445-5434-3212");        Book book2 = new Book("4567-5445-5434-3212");        em.persist(book2);        flushAndClean();        assertThat(book1, equalTo(book2)); // equals    }}正如我們所看到的,現在兩個實體將是平等的。我的問題是同一實體在過渡到管理狀態時是否應該平等。因此,在這種情況下如何正確地重新定義等號。
查看完整描述

2 回答

?
三國紛爭

TA貢獻1804條經驗 獲得超7個贊

根據這篇文章 equals,hashCode應該與狀態無關。如果你只覆蓋了第一個,那就不好了,可能會導致奇怪的錯誤。他們需要有一份合同。

最簡單的方法是使用 lombok - 用 注釋您的類,@EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false)并與 比較使用的字段@EqualsAndHashCode.Include


查看完整回答
反對 回復 2022-07-20
?
蠱毒傳說

TA貢獻1895條經驗 獲得超3個贊

當我前一陣子研究這個問題時,我得出結論,沒有一個正確的答案。


我最終只檢查了and中的@Id屬性,因為這似乎表現最好。(我們不使用任何s;它可以代替它,但堅持使用 s 可能更安全。)equals()hashCode()@NaturalId@Id


我認為我發現的唯一潛在問題是,如果一個新實例在被持久化之前被添加到集合中。實際上,這在我們的項目中從未發生過,因此效果很好。(如果在您的項目中確實如此,您可能仍然會發現這是最好的權衡,以避免當持久對象出現在集合中時出現問題,這更常見。)


正如其他答案所指出的那樣,如果您覆蓋,equals()您還必須覆蓋hashCode(),以確保相等的對象始終具有相同的哈希碼。(問題的第一個示例確實符合這一點,盡管這兩種方法不檢查所有相同的字段可能有點令人困惑。)


順便說一下,在 Kotlin 中,這兩種方法變得易于管理:


override fun equals(other: Any?) = other === this

                                || (other is MyEntity && entityId == other.entityId)


override fun hashCode() = entityId

(我為什么喜歡 Kotlin 的另一個例子!)


查看完整回答
反對 回復 2022-07-20
  • 2 回答
  • 0 關注
  • 160 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號