我应该在JPA实体中编写equals()方法吗?

我想检查实体是否在另一个实体的集合成员( @OneToMany@ManyToMany )中:

 if (entity2.getEntities1().contains(entity1)) { } 

不必要。 有三个选项:

  • 不要重写 – 因此你将会使用实例。 如果只使用连接到会话的实体(因此保证是相同的实例)来处理集合,那么这很好。 这在很多情况下(对我而言)是首选方式,因为在覆盖时它需要更less的代码和更less的考虑

  • 用业务键重写hashCode()equals() 。 这可能是识别实体的属性的子集。 例如,对于User ,良好的商业密钥可能是usernameemail 。 这被认为是很好的做法。

  • 仅使用ID字段覆盖hashCode()equals() 。 这在某些情况下是好的,特别是如果你有一个手动分配的标识符(如UUID)。 如果你的实体永远不会进入收集也是很好的。 但是对于进入集合的临时实体(没有标识符),会导致问题,所以要小心这个选项。 正如海山人指出的 – 你应该避免它。 一般来说,除非你真的意识到自己在做什么(也许logging下来)

看到这篇文章的更多细节。 还要注意的是, equals()hashCode()是绑定的,应该使用完全相同的字段来实现。

是的,你应该定义相应的equals()hashcode()方法,但是你不应该让id成为其中的一部分。 (请参阅我最近在类似问题中的答案 )

有关这个主题的Hibernate文档中的信息。

我们倾向于让IDE为我们生成hashCode()equals() 。 不过要小心。 当您为JPA实体生成这些方法时。 一些版本的equals()检查类标识

 // ... inside equals() - wrong approach for Entities (cause of generate proxies) if (o == null || this.getClass() != o.getClass()) { return false; } // ... 

这会破坏您的集合与一些JPA库,因为这些库创build代理到您的实体(子类),例如Hibernate中的MyGreatEntity_$$_javassist_7

在实体中总是允许equals()子类。

这是唯一的方法。 你可能想尝试Pojomatic库,它为你做了艰难的工作。

是的你应该!

如果您不覆盖默认的Java.lang.Object equalshashCode实现:

 @Entity(name = "Book") public class Book implements Identifiable<Long> { @Id @GeneratedValue private Long id; private String title; //Getters and setters omitted for brevity } 

merge操作将返回一个不同的对象实例,平等合同将被打破作为解释在这篇文章 。

最好的方法是使用一个商业密钥,像这样:

 @Entity public class Book implements Identifiable<Long> { @Id @GeneratedValue private Long id; private String title; @NaturalId private String isbn; @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Book)) return false; Book book = (Book) o; return Objects.equals(getIsbn(), book.getIsbn()); } @Override public int hashCode() { return Objects.hash(getIsbn()); } //Getters and setters omitted for brevity } 

您也可以使用标识符来实现相等性,但是请注意,hashCode实现应始终返回与我已经提到的相同的文章中所解释的相同的值:

 @Entity public class Book implements Identifiable<Long> { @Id @GeneratedValue private Long id; private String title; @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Book)) return false; Book book = (Book) o; return Objects.equals(getId(), book.getId()); } @Override public int hashCode() { return 31; } //Getters and setters omitted for brevity }