出现了一些此处讨论有关JPA实体以及哪些实体hashCode()/等于()实现应用于JPA实体类。大多数(如果不是全部的话)都依赖于Hibernate,但我想中性地讨论它们JPA实现(顺便说一下,我使用的是EclipseLink)
在以下方面,所有可能的实施都有自己的优点和缺点:
hashCode()/equals()针对列表/集合操作的一致性(不变性)- 是否可以检测到相同的对象(例如来自不同会话、来自延迟加载数据结构的动态代理)
- 实体在分离(或非持久化)状态下的行为是否正确
据我所知,有三种选择:
- 不要超越它们;依赖
Object.equals()和Object.hashCode()hashCode()/equals()工作- 无法识别相同的对象,动态代理存在问题
- 分离实体没有问题
- 基于主键覆盖它们
hashCode()/equals()已损坏- 正确标识(适用于所有托管实体)
- 分离实体的问题
- 基于业务Id(非主键字段;外键如何?)
hashCode()/equals()已损坏- 正确标识(适用于所有托管实体)
- 分离实体没有问题
我的问题是:
- 我是否错过了一个选项和/或赞成/反对的观点?
- 你选择了什么选项?为什么
更新1:
通过“hashCode()/equals()被破坏”,我的意思是连续的hashCode()调用可能会返回不同的值,这些值(在正确实现时)在对象API文档的意义上不会被破坏,但是,当尝试从映射、集或其他基于哈希的集合检索更改的实体时,会出现问题。因此,JPA实现(至少EclipseLink)在某些情况下无法正常工作
更新2:
感谢您的回答,其中大多数都有卓越的品质。
不幸的是,我仍然不确定哪种方法最适合实际应用程序,或者如何确定适合我的应用程序的最佳方法。因此,我将继续讨论这个问题,并希望有更多的讨论和/或意见
阅读这篇关于这个主题的非常好的文章:不要让hibernate窃取您的身份
文章的结论如下:
对象标识在以下情况下很难正确实现
对象被持久化到数据库。然而,问题的根源在于
完全不允许对象在创建之前没有id而存在
保存的。我们可以通过承担责任来解决这些问题
从对象关系映射框架中分配对象ID
比如冬眠。相反,只要
对象被实例化。这使得对象标识变得简单和容易
无错误,并减少域模型中所需的代码量