我想检查实体是否在另一个实体的Collection成员(@OneToMany
或@ManyToMany
)中:
if (entity2.getEntities1().contains(entity1)) { }
答案 0 :(得分:114)
不一定。有三种选择:
不要覆盖 - 因此您将使用实例。当您使用仅附加到会话的实体(因此保证是相同的实例)处理集合时,这很好。在许多情况下,这是(对我而言)首选方式,因为它在覆盖时需要的代码更少,考虑更少
使用商家密钥覆盖hashCode()
和equals()
。这可能是标识实体的属性的子集。例如,对于User
,良好的商家密钥可能是username
或email
。这被认为是一种很好的做法。
仅使用ID字段覆盖hashCode()
和equals()
。在某些情况下这很好,特别是如果您有一个手动分配的标识符(如UUID)。如果您的实体永远不会进入集合,那也没关系。但对于进入集合的瞬态实体(没有标识符),它会导致问题,因此请谨慎使用此选项。正如海员所说 - 你应该避免它。通常,总是,除非您真正了解自己在做什么(并且可能记录下来)
See this article了解更多详情。另请注意,equals()
和hashCode()
是绑定的,应使用完全相同的字段实现。
答案 1 :(得分:13)
是的,您应该定义相应的equals()
和hashcode()
方法,但是您永远不应该让id成为其中之一。 (请参阅类似问题中的this recent answer of mine)
答案 2 :(得分:10)
是的,你应该!
如果您未覆盖默认的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
操作将返回一个不同的对象实例,并且相等合同将被破坏as explain in this post。
最好的方法是使用商业密钥,如下所示:
@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
}
答案 3 :(得分:7)
答案 4 :(得分:5)
我们倾向于让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库,因为这些库创建了你的实体(子类)的代理,比如Hibernate中的例如MyGreatEntity_$$_javassist_7
。
在实体中始终允许equals()
中的子类。
答案 5 :(得分:2)
这是唯一的方法。您可能想尝试Pojomatic库,为您完成艰苦的工作。