【问题标题】:How to implement equals with hibernate without risking losing the symmetric property?如何在不丢失对称属性的情况下使用休眠实现等于?
【发布时间】:2013-01-25 23:32:40
【问题描述】:

在阅读(再次,很久以前应该这样做)正确实施equals和hashcode之后,我得出了这些结论,这对我有用:

如果在 JDK 7 之前:更喜欢使用 Apache commons equalsbuilder 和 hashcodebuilder。 (或番石榴)。 他们的 javadocs 包含如何以良好方式使用它们的示例。

如果 JDK 7++:使用新的 Objects 实用程序类

但是,如果为休眠编写会出现一些特殊要求(请参阅下面的来源) 其中推荐使用 instanceof 而不是 getClass,因为 hibernate 会创建延迟加载的子类代理。

但据我了解,如果这样做会出现另一个潜在问题:使用 getClass 的原因是为了确保 equals 合约的对称属性。 JavaDocs:

*It is symmetric: for any non-null reference values x and y, x.equals(y) 
 should return true if and only if y.equals(x) returns true.*

并且通过使用 instanceof,它可能不是对称的。 示例:B 扩展 A。A 的 equals 对 A 进行 instanceof 检查。B 的 equals 对 B 进行 instanceof 检查。给 A a 和 B b:

a.equals(b) --> 真 b.equals(a) --> 错误

如何在不丢失对称属性的情况下使用 hibernate 实现 equals?用getClass好像不安全,用instanceof也不安全?

答案是永远不要向子类添加重要成员,然后安全地使用 instanceof(对于休眠)?

我阅读的来源:

What issues should be considered when overriding equals and hashCode in Java?

Josh Blochs 优秀著作《Effective Java》中的第 7 条和第 8 条,http://web.archive.org/web/20110622072109/http://java.sun.com/developer/Books/effectivejava/Chapter3.pdf

关于 Java 7:http://www.javacodegeeks.com/2012/11/guavas-objects-class-equals-hashcode-and-tostring.html

【问题讨论】:

    标签: java hibernate java-7 hashcode instanceof


    【解决方案1】:

    如果您想在 equals 方法中比较两个对象的类,您可以在比较它们之前对两个对象使用Hibernate.getClass。然后你就不会遇到麻烦,例如在比较对象和对象的休眠代理时。

    【讨论】:

      【解决方案2】:

      在总结了一些之后,我总结了这个问题:

      • 使用 instanceof,您永远无法将重要成员添加到子类中。( 没有办法扩展一个可实例化的类并添加一个值组件,同时保留 equals 契约 (Bloch)
      • 使用 getClass 违反了 Liskov 替换原则

      朗格斯说http://www.angelikalanger.com/Articles/JavaSolutions/SecretsOfEquals/Equals.html

      • instanceof 测试仅对 final 类或至少方法 equals() 在超类中是 final 的情况下是正确的。后者本质上 意味着没有子类必须扩展超类的状态,但可以 只添加与对象无关的功能或字段 状态和行为,例如瞬态或静态字段。

      另一方面,使用 getClass() 测试的实现总是 遵守 equals() 合同;它们是正确且稳健的。他们 然而,在语义上与实现非常不同 使用 instanceof 测试。使用 getClass() 的实现不允许 子类与超类对象的比较,即使是子类 不添加任何字段,甚至不想覆盖 equals() 。 这种“微不足道”的类扩展例如是添加 为这个“琐碎”定义的子类中的调试打印方法 目的。如果超类通过 getClass() 检查,那么微不足道的扩展将无法比较 到它的超类。这是否是一个问题完全取决于 类的语义和扩展的目的。

      总结 - 将 instanceof 与 final 用于 equals 可避免破坏对称性,并避免休眠“代理”问题。

      链接

      【讨论】:

        【解决方案3】:

        这是一个有趣的问题——当涉及到继承时,将equals 实现为等价关系并非易事。请参阅 Martin Odersky 等人的 this in-depth post。关于实现对象相等。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-12-26
          • 1970-01-01
          • 2023-03-05
          • 1970-01-01
          • 2019-03-14
          • 2022-06-22
          • 2022-11-30
          • 1970-01-01
          相关资源
          最近更新 更多