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

2022-08-31 14:04:41

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

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

答案 1

不一定。有三个选项:

  • 不要覆盖 - 因此您将使用实例。当您使用仅具有附加到会话的实体(因此保证是同一实例)的集合时,这很好。在许多情况下,这是(对我来说)首选方式,因为在覆盖时需要更少的代码和更少的考虑。

  • 覆盖 并使用业务密钥。这可能是标识实体的属性子集。例如,对于一个好的业务键,可能是 或 。这被认为是很好的做法。hashCode()equals()Userusernameemail

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

有关更多详细信息,请参阅此文章。另请注意,和 是绑定的,并且应该使用完全相同的字段来实现这两个字段。equals()hashCode()


答案 2

是的,你应该!

如果不覆盖默认值和实现: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

最好的方法是使用业务密钥,如下所示:

@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
}

您也可以使用标识符来实现相等,但请记住,实现应始终返回相同的值,这对于实体来说并不是一个真正的问题,因为您不会为每个数据库事务获取许多实体,否则,获取数据的成本比使用固定的单个桶惩罚要大几个数量级:hashCodeHashMaphashCode

@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 getClass().hashCode();
    }
 
    //Getters and setters omitted for brevity
}

推荐