此处已经进行了一些 有关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()
调用可能会返回不同的值,也就是(当正确实施)不在的感觉打破Object
API文档,但是当试图从检索改变实体引起的问题Map
, Set
或其他基于哈希Collection
。因此,在某些情况下,JPA实现(至少是EclipseLink)将无法正常工作。
更新2:
谢谢您的回答-大多数都具有卓越的质量。
不幸的是,我仍然不确定哪种方法对实际应用程序将是最好的,或者不确定如何为我的应用程序确定最佳方法。因此,我将保持开放的态度,并希望有更多的讨论和/或意见。
hashcode()
除非在equals()
实现中使用的任何字段发生更改,否则在同一对象实例上的调用应返回相同的值。换句话说,如果您的类中有三个字段,并且您的equals()
方法仅使用其中两个字段来确定实例的相等性,那么hashcode()
如果您更改了这些字段的值之一,则可以期望返回值发生变化-这在您考虑时是有意义的该对象实例不再“等于”旧实例表示的值。