这里已经有一些 关于JPA实体的讨论,以及对于JPA实体类应该使用哪种hashCode()/ equals()实现。它们中的大多数(如果不是全部)都依赖于Hibernate,但是我想中立地讨论它们(通过顺便说一下,我正在使用EclipseLink)。
在以下方面,所有可能的实现都有各自的优点和缺点:
hashCode()/equals()合同一致性(不变性)为List/ Set操作 是否可以检测到相同的对象(例如,来自不同的会话,来自延迟加载的数据结构的动态代理) 实体在分离(或非持久)状态下是否行为正确 据我所知,有三种选择:
Object.equals()
Object.hashCode()
hashCode()/ equals()
Business-Id
hashCode()
equals()
我的问题是:
更新1:
通过“ hashCode()/ equals()被破坏”,我的意思是连续hashCode()调用可能会返回不同的值,也就是(当正确实施)不在的感觉打破ObjectAPI文档,但是当试图从检索改变实体引起的问题Map, Set或其他基于哈希Collection。因此,在某些情况下,JPA实现(至少是EclipseLink)将无法正常工作。
ObjectAPI
Collection
EclipseLink
更新2:
谢谢你的回答-大多数都具有卓越的质量。 不幸的是,我仍然不确定哪种方法最适合实际应用程序,或者如何确定适合我的应用程序的最佳方法。因此,我将保持开放的态度,并希望有更多的讨论和/或意见。
个人已经在不同的项目中使用了这三种策略。我必须说,在我看来,选项1在现实生活中是最可行的。以我的经验,破坏hashCode()/ equals()一致性会导致许多疯狂的错误,因为每次将最终结果添加到集合中之后,相等性的结果都会改变。
但是,还有其他选择(也各有利弊):
a)基于一组不可变的,非null,分配的构造函数,字段的hashCode /等于
(+)所有三个条件均得到保证
(-)字段值必须可用于创建新实例
(-)如果必须更改其中之一,会使处理变得复杂
b)基于由应用程序(在构造函数中)而不是JPA分配的主键的hashCode /等于
(-)你无法利用DB序列之类的简单可靠的ID生成状态
(-)如果在分布式环境(客户端/服务器)或应用程序服务器群集中创建新实体,则会很复杂
c)基于实体构造函数分配的UUID的 hashCode /等于
(-)UUID生成的开销
(-)可能会使用两次相同的UUID,这有一点风险,具体取决于所使用的算法(可由数据库上的唯一索引检测到)