此处已经进行了一些 有关JPA实体的讨论,以及JPA实体类应使用哪种hashCode()/ equals()实现。它们中的大多数(如果不是全部)都依赖于Hibernate,但是我想中立地讨论它们(顺便说一下,我正在使用EclipseLink)。
在以下方面,所有可能的实现都有各自的优点和缺点:
hashCode()/equals()合同一致性(不变性)为List/Set操作- 是否可以检测到相同的对象(例如,来自不同的会话,来自延迟加载的数据结构的动态代理)
- 实体在分离(或非持久)状态下是否行为正确
据我所知,有三种选择:
- 不要覆盖它们;依靠
Object.equals()和Object.hashCode()hashCode()/equals()工作- 无法识别相同的对象,动态代理问题
- 独立实体没有问题
- 根据主键覆盖它们
hashCode()/equals()坏了- 正确的身份(对于所有管理实体)
- 独立实体的问题
- 根据Business-Id(非主键字段;外键如何?)
覆盖它们
hashCode()/equals()坏了- 正确的身份(对于所有管理实体)
- 独立实体没有问题
我的问题是:
- 我错过了一个选项和/或优点/缺点吗?
- 您选择了什么选项,为什么?
更新1:
通过“ hashCode()/ equals()被破坏”,我的意思是连续hashCode()调用可能会返回不同的值,也就是(当正确实施)不在的感觉打破ObjectAPI文档,但是当试图从检索改变实体引起的问题Map, Set或其他基于哈希Collection。因此,在某些情况下,JPA实现(至少是EclipseLink)将无法正常工作。
更新2:
谢谢您的回答-大多数都具有卓越的质量。
不幸的是,我仍然不确定哪种方法对实际应用程序将是最好的,或者不确定如何为我的应用程序确定最佳方法。因此,我将保持开放的态度,并希望有更多的讨论和/或意见。
hashcode()除非在equals()实现中使用的任何字段发生更改,否则在同一对象实例上的调用应返回相同的值。换句话说,如果您的类中有三个字段,并且您的equals()方法仅使用其中两个字段来确定实例的相等性,那么hashcode()如果您更改了这些字段的值之一,则可以期望返回值发生变化-这在您考虑时是有意义的该对象实例不再“等于”旧实例表示的值。
