慕工程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貢獻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 的另一個例子!)
添加回答
舉報
0/150
提交
取消