我有一个BaseEntity,它提取id和version属性。此类还基于PK(id)属性实现hashcode和equals。
BaseEntity{
Long id;
Long version;
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
BaseEntity other = (BaseEntity) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
}
现在两个实体A和B扩展了BaseEntity,如下所示
A extends BaseEntity{
`B b`
B getB(){return b;)
void setB(B b){this.b=b;}
}
B extends BaseEntity{
}
object b1;
object a1;
a1.set(b1);
session.save(a1) //cascade save;
关闭会话 使用lazy b加载a并尝试a1.getB()。equals(b1)给出false 但如果我与a1.getB()。getId()。equals(b1.getId())比较,那么真的很奇怪! 我认为这是因为java辅助代理对象,无论如何要解决这个问题?
答案 0 :(得分:19)
为了能够延迟加载a.b
关联,Hibernate会将b
中的a
字段设置为代理。代理是扩展B但不是B的类的实例。因此,在将非代理B实例与代理B实例进行比较时,您的equals()方法将始终失败,因为它比较了两个对象的类:
if (getClass() != obj.getClass())
return false;
对于Hibernate实体,您应该用
替换它if (!(obj instanceof B)) {
return false;
}
另外,请注意
equals()
和hashCode()
,而是使用自然标识符。使用ID实现它可能会导致问题,因为实体在保存并生成ID之前没有ID a.b
。因此a.b
将初始化为代理,它是B的子类,但不是B1或B2的子类。因此,hashCode()
和equals()
方法应在B中实现,但不能在B1和B2中重写。如果两个B实例是B的实例,并且具有相同的标识符,则应认为它们是相等的。答案 1 :(得分:11)
我使用Hibernate.getClass
多年,我从未发现过问题:
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (Hibernate.getClass(this) != Hibernate.getClass(obj)) {
return false;
}
... check for values
return true;
}
答案 2 :(得分:1)
你也可以让它以这种方式运作,如果你不知道实例是B(如果你的equals
在超类中可能会发生的话),这是有用的
if (HibernateProxyHelper.getClassWithoutInitializingProxy(this) != HibernateProxyHelper.getClassWithoutInitializingProxy(obj))
return false
答案 3 :(得分:-1)
这主要是标准Java继承的影响。
a1.getB().equals(b1)
使用Object.equals()
(除非您在类中重写了equals()),如果a1.getB()和b1是同一个实例,则只返回true。我不知道你到底做了什么(你的代码格式被破坏了),但看起来你已经在另一个会话中再次加载a
,所以你得到a
的新实例和a.getB()
,因此Object.equals()
返回false。
a1.getB().getId().equals(b1.getId())
使用Long.equals()
,如果long值相同(即使对于Long对象的不同实例),则返回true,并且这些值显然是相同的。