已经多次讨论过如何为实体重新定义 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
提交
取消
