我应该在JPA实体中编写equals()方法吗?
我想检查实体是否在另一个实体的集合成员( @OneToMany
或@ManyToMany
)中:
if (entity2.getEntities1().contains(entity1)) { }
不必要。 有三个选项:
-
不要重写 – 因此你将会使用实例。 如果只使用连接到会话的实体(因此保证是相同的实例)来处理集合,那么这很好。 这在很多情况下(对我而言)是首选方式,因为在覆盖时它需要更less的代码和更less的考虑
-
用业务键重写
hashCode()
和equals()
。 这可能是识别实体的属性的子集。 例如,对于User
,良好的商业密钥可能是username
或email
。 这被认为是很好的做法。 -
仅使用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
equals
和hashCode
实现:
@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 }