2010-12-08 69 views
42

我要检查,如果实体是在其他单位的收集部件(@OneToMany@ManyToMany):我应该在JPA实体中编写equals()方法吗?

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

为了阐述这个问题的动机:[`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

+0

另请参阅http://stackoverflow.com/a/39827962/548473(spring-data-jpa的实现) – GKislin 2016-10-03 09:07:48

回答

104

不一定。有三种选择:

  • 不重写 - 因此您将使用实例。如果仅使用附加到会话的实体处理集合(因此保证它们是相同的实例),这很好。这对于我来说是很多情况下的首选方式,因为它需要更少的代码,并且在覆盖时需要考虑更少的代码。

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

  • 覆盖hashCode()equals()仅使用ID字段。在某些情况下这很好,特别是如果您有手动分配的标识符(如UUID)。如果您的实体永远不会收藏,这也很好。但是对于进入集合的临时实体(没有标识符),会导致问题,所以请谨慎使用此选项。正如海南人所说 - 你应该避免它。一般来说,总是,除非你真的知道你在做什么(也许它文档)

See this article了解更多详情。还要注意equals()hashCode()是捆绑在一起的,并且应该使用完全相同的字段来实现。

2

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

12

是的,你应该定义相应的equals()hashcode()方法,但你千万不要让ID来的任一部分。 (见类似问题中的this recent answer of mine

+0

我已经不时用等于和哈希代码覆盖只有id,并且它工作正常。真的,我考虑过使用情况,以及我不会使用瞬态实体的事实。所以我不会说完全'从来没有':) – Bozho 2010-12-08 14:23:29

5

我们倾向于让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()中的子类。

0

是的,你应该!

如果不覆盖缺省Java.lang.ObjectequalshashCode实现:

@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 
} 
相关问题