在Java中为UDT提供#equals
实现时,其中一个条件是传递的参数对象必须是当前类的实例,否则我们会快速return false
看Effective Java (EJ2)。但是,在使用Hibernate 4时,由于延迟加载,#equals
条件将失败,因此我们最终可能会遇到javassist代理实例。什么是克服这个问题的最佳选择?我能想到的几个选择是:
equals
实施以考虑代理案例。缺点:可维护性收费,对Hibernate代理基础设施的硬连线依赖,hacky,实体或域模型应该与所使用的ORM无关,即因为它们可能在不需要ORM的不同上下文中重用,例如Swing UI。equals
之前检查它是否是代理。缺点:并非总是可行,即处理equals
的集合和隐式调用,例如Map。更新
再次回顾EJ2我认为以下内容适用于所有场景(Type-Type,Type-Proxy,Proxy-Type和Proxy-Proxy),但正如下面的一条评论中指出的那样,它可能会永远循环比较完全不同的类型,例如Person.equals(Employee)
并且两者都使用相同的等于EJ2标准。
if (this.getClass() != anObject.getClass())
{
return anObject.equals(this);
}
答案 0 :(得分:11)
.equals
- 方法。
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!getClass().isAssignableFrom(obj.getClass()))
return false;
AbstractEntity other = (AbstractEntity) obj;
if (getId() == null) {
if (other.getId() != null)
return false;
} else if (!getId().equals(other.getId()))
return false;
return true;
诀窍是不要将类比较为相同但使用isAssignableFrom
- 方法。另一个技巧是不使用直接属性(other.id
),但使用get方法(other.getId()
)
答案 1 :(得分:7)
我对Willem de Wit的回答不予置评。我需要发布一个新答案。
要解决djechelon的问题,你应该替换这一行:
if (!getClass().isAssignableFrom(obj.getClass()))
的
if ( !obj.getClass().isAssignableFrom(getClass()) && !getClass().isAssignableFrom(obj.getClass()) )
然后,您将确保equals适用于所有场景(Type-Type,Type-Proxy,Proxy-Type和Proxy-Proxy)。
我也没有声誉来表达你的答案。我太悲惨了!
答案 2 :(得分:1)
你可以做两件事: 1.将equals更改为使用instanceof而不是类相等。代理的类型不等于实体的类型,而是扩展实体的类型。
答案 3 :(得分:1)
上面的DHansen的答案很接近,但对我来说(使用Hibernate)这解决了这个问题:
if (!Hibernate.getClass(this).equals(Hibernate.getClass(obj))) {
return false;
}
正如Dr. Hans-Peter Störr
同样重要的是始终使用上面Willem de Wit建议的'getters'。