我要检查,如果实体是在其他单位的收集部件(@OneToMany
或@ManyToMany
):我应该在JPA实体中编写equals()方法吗?
if (entity2.getEntities1().contains(entity1)) { }
我要检查,如果实体是在其他单位的收集部件(@OneToMany
或@ManyToMany
):我应该在JPA实体中编写equals()方法吗?
if (entity2.getEntities1().contains(entity1)) { }
不一定。有三种选择:
不重写 - 因此您将使用实例。如果仅使用附加到会话的实体处理集合(因此保证它们是相同的实例),这很好。这对于我来说是很多情况下的首选方式,因为它需要更少的代码,并且在覆盖时需要考虑更少的代码。
用业务密钥覆盖hashCode()
和equals()
。这可能是识别实体的属性的子集。例如,对于User
,良好的业务密钥可能是username
或email
。这被认为是很好的做法。
覆盖hashCode()
和equals()
仅使用ID字段。在某些情况下这很好,特别是如果您有手动分配的标识符(如UUID)。如果您的实体永远不会收藏,这也很好。但是对于进入集合的临时实体(没有标识符),会导致问题,所以请谨慎使用此选项。正如海南人所说 - 你应该避免它。一般来说,总是,除非你真的知道你在做什么(也许它文档)
See this article了解更多详情。还要注意equals()
和hashCode()
是捆绑在一起的,并且应该使用完全相同的字段来实现。
这是唯一的办法。你可能想尝试Pojomatic库,它为你做了艰难的工作。
是的,你应该定义相应的equals()
和hashcode()
方法,但你千万不要让ID来的任一部分。 (见类似问题中的this recent answer of mine)
我已经不时用等于和哈希代码覆盖只有id,并且它工作正常。真的,我考虑过使用情况,以及我不会使用瞬态实体的事实。所以我不会说完全'从来没有':) – Bozho 2010-12-08 14:23:29
我们倾向于让IDE为我们生成hashCode()
和equals()
。但要小心。当您为JPA实体生成这些方法时。对于阶级身份
// ... inside equals() - wrong approach for Entities (cause of generate proxies)
if (o == null || this.getClass() != o.getClass()) {
return false;
}
// ...
这将打破你收藏的一些JPA库,这些库创建代理到您的实体(子类),例如像MyGreatEntity_$$_javassist_7
在Hibernate中的equals()
检查某些版本。
实体总是允许equals()
中的子类。
是的,你应该!
如果不覆盖缺省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
}
您还可以使用平等的标识,但是记住,哈希码实现应该总是返回相同的值相同的解释后,我已经提到:
@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
}
为了阐述这个问题的动机:[`Collection.contains(JpaEntity someObject)`](http://docs.oracle.com/javase/7/docs/api/java /util/Collection.html#contains(java.lang.Object))需要合理的`JpaEntity.equals(...)`方法。 – Abdull 2013-02-10 14:51:58
另请参阅http://stackoverflow.com/a/39827962/548473(spring-data-jpa的实现) – GKislin 2016-10-03 09:07:48