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

4
使用JPA时,我遇到了一些关于equals()hashcode()的问题,特别是对于尚未持久化的新实体。
我在stackoverflow上找到了以下答案: Should I write equals() methods in JPA entities? 这个答案涉及到Hibernate sessions。我没有使用Hibernate(而是EclipseLink),也不了解JPA提供商的实现细节,例如这些“sessions”。
我的问题是,从JPA的角度来看,什么是Hibernate session?或者更具体地说:如果我不重写equals()hashcode(),在哪些情况下会出现两个表示同一实体(如果存在一个业务主键,则为相同)的对象不“ 相等”(这意味着equals()返回false)的问题?
是否使用相同的EntityManager实例就足以避免这些问题(这意味着,“session”和“EntityManager”可以在此上下文中等效使用)?
注意:我并非所有表都有可用的业务主键,因此不能应用在equals()hashcode()中使用业务主键属性的解决方法。
2个回答

6

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

在持久性上下文中,标识保持不变,因此默认的equals和hashCode函数会起作用。

对于分离对象,它们将具有不同的标识,因此除非您重写它以使用Id或某些其他标准,否则equals不会返回true。这不会对EclipseLink造成问题,但是您的应用程序可能对此有依赖。

通常,如果您的对象在集合或映射中使用,则应正确实现equals和hashCode,但是EclipseLink始终在内部使用标识映射和集合,因此在内部不应出现任何问题。


顺便提一下,关于这个回答是否权威:请看詹姆斯的个人资料! - Arjan
@James:EclipseLink是否仍然总是使用identity set?我们有一个特别糟糕的hashCode实现,在删除时遇到了巨大的性能问题。查看UnitOfWorkImpl的代码,我发现删除依赖项都是使用普通的HashMap / HashSet来跟踪的。这是一个错误还是设计上的问题?无论哪种方式,它似乎都与EclipseLink不需要从这些方法中获取任何东西的想法相矛盾。 - Mark Peters

1

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接