【问题标题】:Correct way of Implementation of equals() method for JPA entitiesJPA实体的equals()方法的正确实现方式
【发布时间】:2023-03-25 19:55:02
【问题描述】:

我使用 Eclipse 通过选择感兴趣的字段/属性为我的 JPA 实体生成 hashcode()equals() 方法。

但是,我观察到 Eclipse 似乎在生成的 equals 方法中添加了以下行:

    if (getClass() != obj.getClass())
        return false;

进行上述检查似乎是合乎逻辑的,但我在所有 JPA 实体中都使用 LAZY 加载的关系,并且我观察到,在某些情况下,当 obj 的类是某种代理类并且主要对象是有问题的实体 - 我检查了正在比较的对象类,两者并不完全相同,因此上述条件评估为 false,即使对象代表数据库中的相同记录。

因此,我的问题是当我们为 JPA 实体实现 equals() 方法时,我们是否应该比较对象的类。

【问题讨论】:

  • 通常情况下,该检查用于防止ClassCastException。代理类和主实体类是否都有一个共同的父级供您转换?
  • 我尝试将Student 类的实例与Student 类实例的集合进行比较——第一个实例是从数据库中读取的,而集合是延迟初始化的,因为它是与另一个的子关系的一部分实体,比如College
  • 这并不能真正回答我的问题。您的代码可以在没有if 语句的情况下运行吗?如果是这样,您可以更加宽容,使用instanceof 检查而不是比较getClass()
  • 我将不得不检查这一点 - 同时,其他人是否也应该面临这个问题,因为我不确定我是否通过使用延迟加载的实例来做任何不寻常的事情?
  • 我认为你只能依赖instanceof 如果涉及代理并且你想要一个通用的Object.equals 方法。对于同一类/类型的实体,Eclipse 方式必须有效

标签: java hibernate jpa


【解决方案1】:

建议对 JPA 实体使用 业务密钥相等。 自动生成的等号使用所有字段。

您的实体很可能具有技术性自动生成的主键(id 字段)。在实体被持久化后,该字段由数据库填充。 如果您有自动生成的 equals/hashcode,它包括所有类字段 - 包括该 id 字段。 因此,您的实体的 equals/hashcode 将在您持久化后更改,而不更改任何其他字段(持久化 id 之前将为空,持久化之后不为空)。

更多详情请阅读 https://docs.jboss.org/hibernate/stable/core.old/reference/en/html/persistent-classes-equalshashcode.html

这是 Hibernate 参考,但所有与主键相关的概念都应适用于任何 JPA 提供者。

【讨论】:

  • 完全同意@Bartosz Bilicki,因为JPA 实体它只是数据库行的Java 视图。根据sql文档The PRIMARY KEY constraint uniquely identifies each record in a database table。因此,如果您有两个具有相同 ID 的实体,则意味着它是同一个实体。
  • 我不使用类的所有字段/属性 - 在 Eclipse 中,当您使用选项 Source -> Generated equals and hashcode 时,它提供了一个 GUI 来选择将建立自然平等的字段。
猜你喜欢
  • 1970-01-01
  • 2012-10-01
  • 2010-12-28
  • 1970-01-01
  • 2011-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-24
相关资源
最近更新 更多