JPA hashCode() / equals() 困境

新手上路,请多包涵

这里有 一些 关于 JPA 实体的 讨论,哪些 hashCode() / equals() 实现应该用于 JPA 实体类。它们中的大多数(如果不是全部)都依赖于 Hibernate,但我想讨论它们 JPA-implementation-neutrally(顺便说一下,我正在使用 EclipseLink)。

所有可能的实现在以下方面都有自己的 优点缺点

  • hashCode() / equals() 合同 符合性(不变性) List / Set 操作
  • 是否可以检测到 相同 的对象(例如来自不同会话、来自延迟加载的数据结构的动态代理)
  • 实体在 分离(或非持久)状态下的 行为是否正确

据我所知,有 三个选项

  1. 不要覆盖它们;依靠 Object.equals()Object.hashCode()
    • hashCode() / equals() 工作
    • 无法识别相同的对象,动态代理的问题
    • 分离实体没有问题
  2. 根据 主键 覆盖它们
    • hashCode() / equals() 坏了
    • 正确的身份(对于所有托管实体)
    • 分离实体的问题
  3. 根据 Business-Id 覆盖它们(非主键字段;外键呢?)
    • hashCode() / equals() 坏了
    • 正确的身份(对于所有托管实体)
    • 分离实体没有问题

我的问题是:

  1. 我错过了一个选项和/或赞成/反对点吗?

  2. 你选择了什么选项,为什么?

更新 1:

通过“ hashCode() / equals() 已损坏”,我的意思是连续的 hashCode() 调用可能返回不同的值,即(正确实施时)没有损坏of the Object API documentation, but which causes problems when trying to retrieve a changed entity from a Map , Set or other hash-based Collection .因此,JPA 实现(至少是 EclipseLink)在某些情况下将无法正常工作。

更新 2:

谢谢你的回答——他们中的大多数都具有非凡的品质。

不幸的是,我仍然不确定哪种方法最适合实际应用程序,或者如何确定最适合我的应用程序的方法。所以,我会保持这个问题的开放性,并希望有更多的讨论和/或意见。

原文由 MRalwasser 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 864
1 个回答

阅读关于该主题的这篇非常好的文章: 不要让 Hibernate 窃取您的身份

文章的结论是这样的:

当对象被持久化到数据库时,对象标识很难正确实现。但是,问题完全源于允许对象在保存之前没有 id 存在。我们可以通过将分配对象 ID 的责任从 Hibernate 等对象关系映射框架中移开来解决这些问题。相反,可以在实例化对象后立即分配对象 ID。这使得对象标识简单且无错误,并减少了域模型中所需的代码量。

原文由 Stijn Geukens 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题