Java 使用EclipseLink的JPA实体的equals()和hashcode()

Java 使用EclipseLink的JPA实体的equals()和hashcode(),java,jpa,equals,Java,Jpa,Equals,使用JPA,我偶然发现了equals()和hashcode()的问题,特别是对于尚未持久化的新创建实体 我在stackoverflow中找到了以下答案: 这个答案是关于Hibernate会话的。我不使用Hibernate(但使用EclipseLink),也不知道JPA提供者的实现细节,比如这些“会话” 我的问题是,就JPA而言,什么是Hibernate会话?或者,更具体地说:如果我不重写equals()和hashcode(),在哪些情况下,我会遇到表示相同实体的两个对象(如果存在相同的业务密钥

使用JPA,我偶然发现了
equals()
hashcode()
的问题,特别是对于尚未持久化的新创建实体

我在stackoverflow中找到了以下答案:

这个答案是关于Hibernate会话的。我不使用Hibernate(但使用EclipseLink),也不知道JPA提供者的实现细节,比如这些“会话”

我的问题是,就JPA而言,什么是Hibernate会话?或者,更具体地说:如果我不重写
equals()
hashcode()
,在哪些情况下,我会遇到表示相同实体的两个对象(如果存在相同的业务密钥)不“相等”的问题(这意味着
equals()
返回false)

使用相同的EntityManager实例是否足以避免这些问题(这意味着“会话”和“EntityManager”在此上下文中是否可以等效使用?)


注意:我没有适用于所有表的可用业务密钥,因此无法应用在
equals()
hashcode()
中使用业务密钥属性的解决方案。

您可以有同一实体的两个分离实例,或者一个附加实例和一个分离实例,因此它们不相等,因为默认的equals方法比较物理地址


如果没有业务密钥,几乎不可能为实体实现好的equals方法。即使对于具有业务密钥的实体,如果该业务密钥是可变的,我们也注定要失败。

EclipseLink对equals()和hashCode()没有任何特定要求(即使在Id类上)

在持久性上下文中,标识被维护,因此默认的equals和hashCode将起作用

对于分离的对象,它们将具有不同的标识,因此equals不会返回true,除非您重写它以使用Id或其他一些条件。这不会导致EclipseLink出现问题,但您的应用程序可能依赖于此


一般来说,如果对象在集合或映射中使用,则应正确实现equals和hashCode,但EclipseLink始终在内部使用标识映射和集合,因此在内部应该没有问题。

作为旁白,这是一个权威答案:@詹姆斯:日食总是使用标识集,这(仍然)是真的吗?我们有一个特别糟糕的hashCode实现,并且在delete上遇到了巨大的性能问题。查看UnitOfWorkImpl的代码,我发现删除依赖项都是使用vanilla HashMap/HashSet跟踪的。这是一个bug还是出于设计?不管怎样,它似乎与EclipseLink不需要这些方法的任何东西的观点相矛盾。