Jig*_*ekh 11 proxy hibernate equals
我有一个BaseEntity抽象id和版本属性.此类还基于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;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,两个实体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;
Run Code Online (Sandbox Code Playgroud)
close会话加载一个懒惰的b并尝试a1.getB().equals(b1)给出false,但如果我与a1.getB()进行比较.getId().equals(b1.getId())然后给出真正的奇怪!! 我认为这是因为java辅助代理对象,反正要解决这个问题?
JB *_*zet 21
为了能够延迟加载a.b关联,Hibernate将b字段设置a为代理.代理是扩展B但不是B的类的实例.因此,在将非代理B实例与代理B实例进行比较时,您的equals()方法将始终失败,因为它比较了两个对象的类:
if (getClass() != obj.getClass())
return false;
Run Code Online (Sandbox Code Playgroud)
对于Hibernate实体,您应该将其替换为
if (!(obj instanceof B)) {
return false;
}
Run Code Online (Sandbox Code Playgroud)
另外,请注意
equals()和hashCode()使用ID,而是使用自然标识符.使用ID实现它可能会导致问题,因为实体在保存并生成ID之前没有IDa.b在加载之前无法知道哪种类型(B1或B2).因此a.b将初始化为代理,它是B的子类,但不是B1或B2的子类.所以hashCode()和equals()方法应该在B中实现,但不能在B1和B2中重写.如果两个B实例是B的实例,并且具有相同的标识符,则应认为它们是相等的.Ral*_*lph 12
我使用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;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6525 次 |
| 最近记录: |