当前位置: 首页 > 面试题库 >

如何在不冒失去对称性的风险的情况下实现与休眠相等?

宰父俊彦
2023-03-14
问题内容

阅读完(再次,应该很久以前就应该这样做)正确地实现equals和hashcode之后,我得出以下结论,这对我有用:

如果是JDK 7之前的版本 :建议使用Apache Commons
equalsbuilder和hashcodebuilder。(或番石榴)。他们的javadocs包含如何正确使用它们的示例。

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

但是,如果编写用于hibernate的 代码,则会出现一些特殊要求(请参阅更深层的资料),其中有一些建议的用法是使用 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的检查实例。B的equals进行B的检查实例。给A a和B b:

a.equals(b)-> true b.equals(a)-> false

如何在不冒失去对称性的风险的情况下实现与hibernate相等?看来使用getClass时不安全,使用instanceof时也不安全?

答案是从不向子类中添加重要成员,然后再安全地使用instanceof(对于处于hibernate状态的人)吗?

我阅读的资料:

在Java中重写equals和hashCode时应考虑哪些问题?

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


问题答案:

在提出更多建议后,我总结了以下问题:

  • 使用instanceof,就永远不能向子类中添加重要的成员。(在保留等价合约的同时,无法扩展可实例化的类并添加值组件(Bloch)
  • 使用getClass会违反Liskov替换原则

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

* test的instanceof测试仅对最终类是正确的,或者至少在父类中equals()方法是最终的。后者实质上意味着没有子类必须扩展超类的状态,而只能添加与对象的状态和行为无关的功能或字段,例如瞬态或静态字段。

另一方面,使用getClass()测试的实现始终符合equals()合同;他们是正确和强大的。但是,它们在语义上与使用instanceof
test的实现有很大不同。使用getClass()的实现不允许将子类与超类对象进行比较,即使子类未添加任何字段并且甚至不希望覆盖equals()也不行。这种“琐碎”的类扩展例如是在为该“琐碎”目的而定义的子类中添加了调试打印方法。如果超类禁止通过getClass()检查进行混合类型比较,那么普通扩展将无法与其超类进行比较。

总结-将instanceof与final for equals一起使用可避免破坏对称性,并避免hibernate的“代理”问题。



 类似资料:
  • 问题内容: 我有一个关于乐观锁定Hibernate的问题。我试图深入了解Hibernate的乐观锁定,但是我有一个疑问。Hibernate使用版本方法(整数或时间戳)来实现乐观锁定。要进行配置,您可以使用@Version批注(或xml配置)并创建一个version属性。另一个选项是使用optimistic- lock =“ all”属性进行配置而不进行版本控制。 我的问题是,如果您没有定义任何版本

  • 问题内容: 我正在使用Hibernate + JPA作为我的ORM解决方案。 我正在使用HSQL进行单元测试,并使用PostgreSQL作为真正的数据库。 我希望能够将Postgres的本机UUID类型与Hibernate一起使用,并在其String表示形式中将UUID与HSQL一起用于单元测试(因为HSQL没有UUID类型)。 我正在为Postgres和HSQL单元测试使用具有不同配置的持久性X

  • 问题内容: 如果我要使用DefaultServeMux(我将其指定为ListenAndServe的第二个参数来指定),那么我可以访问,您可以在Go Wiki的以下示例中看到该: 在当前代码中,我无法使用DefaultServeMux,即我将自定义处理程序传递给ListenAndServe 因此,我没有内置的代码。但是,我必须将一些授权代码修改为需要类似的授权代码。例如,如果我一直在使用Defaul

  • 问题内容: 据我了解(如果我错了,请纠正我),Hibernate使用对象引用来检查对象的相等性。当Hibernate识别同一数据库记录中有多个对象附加时,它将引发以下异常。 我的问题是,Hibernate是否使用方法检查对象是否相等(默认的equal方法使用对象引用)?如果为true,则重写的方法会改变Hibernate的行为吗? 注意:我的问题不是关于Hibernate持久对象中的实现或方法问题

  • 问题内容: 我有三个实体。那些是: 在这三个实体中,我想执行以下sql: 在这种情况下,实体与实体没有直接关系。实体具有通过的关系。如何使用休眠条件动态查询实现此目的? 问题答案: 你可以这样:

  • //类B扩展类并添加一个附加变量 //这是主类 在不使用铸造的情况下如何设计解决上述问题?很抱歉问了这个低级的问题(我是java新手)。